Python中的任何序列(可迭代的对象)都可以通过赋值操作进行拆分,包括但不限于元组、列表、字符串、文件、迭代器、生成器等。

元组拆分

元组拆分是最为常见的一种拆分,示例如下:

p = (4, 5)
x, y = p
print(x, y) # 4 5

如果写成

x, y, z = p

那么就会抛出ValueError异常:“not enough values to unpack (expected 3, got 2)”

如果写成

p = (4, 5, 6)
x, y = p

那么就会抛出ValueError异常:“too many values to unpack (expected 2)”

字符串拆分

字符串的拆分示意如下:

s = 'Hello'
a, b, c, d, e = s
print(a) # H

拆分时丢弃值

如果在拆分时想丢弃某些特定的值,可以用一个用不到的变量名来作为丢弃值的名称(常选'_'做为变量名),如下所示:

s = 'Hello'
a, b, _, d, _ = s
print(a) # H

嵌套序列拆分

Python也提供简洁的对嵌套序列进行拆分的语法。如下所示我们对一个比较复杂的异质列表进行拆分:

data = ['zhy', 50, 123.0, (2000, 12, 21)]
name, shares, price, (year, month, day) = data
print(year) # 2000

如果你想完整地得到(2000, 12, 21)这个表示时间戳的元组,那么你就得这样写:

data = ['zhy', 50, 123.0, (2000, 12, 21)]
name, shares, price, date = data
print(date) # (2000, 12, 21)

从任意长度的可迭代对象中拆分

之前我们说过,如果我们想从可迭代对象中分解出\(N\)个元素,但如果这个可迭代对象长度超过\(N\),则会抛出异常"too many values to unpack"。针对这个问题的解决方案是采用"*"表达式。

比如我们给定学生的分数,想去掉一个最高分和一个最低分,然后对剩下的学生求平均分,我们可以这样写:

def avg(data: list):
return sum(data)/len(data)
# 去掉最高分,最低分然后做均分统计
def drop_first_last(grades):
first, *middle, last = grades
return avg(middle)
print(drop_first_last([1,2,3,4])) # 2.5

还有一种情况是有一些用户记录,记录由姓名+电子邮件+任意数量的电话号码组成,则我们可以这样分解用户记录:

record = ['zhy', 'zhy1056692290@qq.com', '773-556234', '774-223333']
name, email, *phone_numbers = record
print(phone_numbers) # ['773-556234', '774-223333']

事实上,如果电话号码为空也是合法的,此时phone_numbers为空列表。

record = ['zhy', 'zhy1056692290@qq.com']
name, email, *phone_numbers = record
print(phone_numbers) # []

还有一种使用情况则更为巧妙。如果我们需要遍历变长元组组成的列表,这些元组长度不一。那么此时*表达式可大大简化我们的代码。

records = [('foo', 1, 2), ('bar', 'hello'), ('foo', 3, 4)]
for tag, *args in records:
if tag == 'bar':
print(args)
# ['hello']

在对一些复杂的字符串进行拆分时,*表达式也显得特别有用。

line = "nobody:*:-2:-2:-2:Unprivileged User:/var/empty:/usr/bin/false"
uname, *fields, home_dir, sh = line.split(':')
print(home_dir) # /var/empty

*表达式也可以和我们前面说的嵌套拆分和变量丢弃一起结合使用。

record = ['ACME', 50, 123.45, (128, 18, 2012)]
name, *_, (*_, year) = record
print(year) # 2012

最后再介绍*表达式用于递归函数的一种黑魔法,比如与递归求和结合可以这样写:

items = [1, 10, 7, 4, 5, 9]
def sum(items):
head, *tail = items
return head + sum(tail) if tail else head
print(sum(items)) # 36

不过,Python由于自身递归栈的限制,并不擅长递归。我们最后一个递归的例子可以做为一种学术上的尝试,但不建议在实践中使用它。

参考文献

  • [1] Martelli A, Ravenscroft A, Ascher D. Python cookbook[M]. " O'Reilly Media, Inc.", 2005.

Python技法1:变长和定长序列拆分的更多相关文章

  1. loadrunner socket协议问题归纳(4)---buffer接收变长和定长的数据

    测试场景:聊天系统 用户登录后,要先向服务器发送用户名,然后可以发送聊天信息,同时也可以接受聊天信息. 如果接受的字符为定长时,可以设定接受长度.recv buf2 66 #include " ...

  2. 报文格式:xml 、定长报文、变长报文

    目前接触到的报文格式有三种:xml .定长报文.变长报文 . 此处只做简单介绍,日后应该会深入学习到三者之间如何解析,再继续更新.——2016.9.23 XML XML 被设计用来传输和存储数据. H ...

  3. 快学Scala 第三课 (定长数组,变长数组, 数组循环, 数组转换, 数组常用操作)

    定长数组定义: val ar = new Array[Int](10) val arr = Array("aa", "bb") 定长数组赋值: arr(0) = ...

  4. Python 数据处理----对定长数据的处理

    场景: 有时候我们对大量数据进行处理,对性能要求很高,而且数据都是定长的,比如对移动信息登记表进行处理:名字 身份证信息 手机号码 这些都是定长的,今天小花来教大家如何对此类数据进行处理. 步骤一: ...

  5. 定长内存池之BOOST::pool

    内存池可有效降低动态申请内存的次数,减少与内核态的交互,提升系统性能,减少内存碎片,增加内存空间使用率,避免内存泄漏的可能性,这么多的优点,没有理由不在系统中使用该技术. 内存池分类: 1.      ...

  6. django使用pyecharts(6)----django加入echarts_增量更新_定长_坐标轴定长

    六.Django 前后端分离_定时增量更新图表(坐标轴定长) 1.安装 djangorestframework linux pip3 install djangorestframework windo ...

  7. django使用pyecharts(5)----django加入echarts_增量更新_定长

    五.Django 前后端分离_定时增量更新图表定长数据 1.安装 djangorestframework linux pip3 install djangorestframework windows ...

  8. Netty(四)分隔符与定长解码器的使用

    TCP以流的形式进行数据传输,上层的应用协议为了对消息进行划分,往往采用如下的4种方式. (1)消息长度固定,累计读到长度总和为定长len的报文后,就认为读取到了一个完整的消息:然后重新开始读取下一个 ...

  9. javascript实现数据结构:串--定长顺序存储表示以及kmp算法实现

    串(string)(或字符串)是由零个或多个字符组成的有限序列.串中字符的数目称为串的长度.零个字符的串称为空串(null string),它的长度为零. 串中任意个连续的字符组成的子序列称为该串的子 ...

随机推荐

  1. 【Python】 第三周:基本数据类型

    整数 python整数无限制 二进制:以0b或者0B开头,例如: 0b010,-0B101 八进制:以0o或者0O开头,例如:0o123,-0O456 浮点数 浮点数间运算存在不确定尾数,不是bug ...

  2. 耗时一个月,整理出这份Hadoop吐血宝典

    本文目录: 一.HDFS 二.MapReduce 三.Yarn 四.Hadoop3.x 新特性 五.Hadoop 大厂面试真题解析 Hadoop 涉及的知识点如下图所示,本文将逐一讲解: 本文档参考了 ...

  3. HTML中的emment

    emment的优点和使用方法: 优点:Emment是前端开发者必备的工具,使用它可以大大提高前端开发效率. 使用方法:Emment的使用方法非常简单,直接在编辑器上输入HTML和CSS代码的缩写,然后 ...

  4. UltraSoft - Alpha - Scrum Meeting 7

    Date: Apr 22th, 2020. Scrum 情况汇报 进度情况 组员 负责 昨日进度 后两日任务 CookieLau PM 完成课程中心的json格式传递 完成邮箱验证机制 刘zh 前端 ...

  5. OO课第三单元总结

    一.梳理JML语言的理论基础 (1)理论基础 JMl的出现很大程度上一为了行为接口的规范化,用这种语言来指定特定模块的特定功能.JML的核心部分分为三个部分:前置条件(requires).后置条件(e ...

  6. 2021.8.18 NKOJ周赛总结

    两个字总结:安详 T1: NKOJ-6179 NP问题 问题描述: p6pou在平面上画了n个点,并提出了一个问题,称为N-Points问题,简称NP问题. p6pou首先在建立的平面直角坐标系,并标 ...

  7. 运用Tomcat创建第一个web项目

    一.了解Web服务器软件 在部署tomcat前,先说一说web服务器软件是用来干什么的?简单来说,就是web容器,可以部署web项目,让用户通过浏览器来访问这些项目. 1.常见的javaweb服务器软 ...

  8. IDA*、剪枝、较难搜索、扫描——DNA sequence HDU - 1560

    万恶之源 翻译 题意就是给出N个DNA序列,要求出一个包含这n个序列的最短序列是多长 这是一道搜索题,为什么呢?从样例可以感受到,我们应该从左往右"扫描",从n个DNA序列中取出某 ...

  9. populating-next-right-pointers-in-each-node-ii leetcode C++

    Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tre ...

  10. JAVA笔记5__构造块、静态块/单例设计模式/继承/final关键字/super关键字

    public class Main { { //构造块(在构造对象时调用,先于构造方法执行) System.out.println("我是构造块!"); } static{ //静 ...