Python技法-序列拆分
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技法-序列拆分的更多相关文章
- Python技法1:变长和定长序列拆分
Python中的任何序列(可迭代的对象)都可以通过赋值操作进行拆分,包括但不限于元组.列表.字符串.文件.迭代器.生成器等. 元组拆分 元组拆分是最为常见的一种拆分,示例如下: p = (4, 5) ...
- Python基本序列-字典
Python 基本序列-字典 字典(dict)是"键-值 对"的无序可变序列,字典中的每个元素包含两部分,"键"和"值". 字典中的&quo ...
- Python常见序列详解
一.Python中序列的分类 常见序列类型包括字符串(普通字符串和unicode字符串),列表和元组.所谓序列,即成员有序排列,可通过下标访问. 二.Python序列通用操作 下面我们将分别以字符串. ...
- 孤荷凌寒自学python第八天 初识Python的序列之元组
孤荷凌寒自学python第八天 Python的序列之元组 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) (同步音频笔记:https://www.ximalaya.com/keji/19103 ...
- Python技法:实现简单的递归下降Parser
1. 算术运算表达式求值 在上一篇博文<Python技法:用re模块实现简易tokenizer>中,我们介绍了用正则表达式来匹配对应的模式,以实现简单的分词器.然而,正则表达式不是万能的, ...
- Python技法2:函数参数的进阶用法
1.关键字参数(positional argument)和位置参数(keyword argument) Python函数的参数根据函数在调用时(注意,不是函数定义时)传参的形式分为关键字参数和位置参数 ...
- Python技法:用re模块实现简易tokenizer
一个简单的tokenizer 分词(tokenization)任务是Python字符串处理中最为常见任务了.我们这里讲解用正则表达式构建简单的表达式分词器(tokenizer),它能够将表达式字符串从 ...
- [Python笔记]序列(一)索引、分片
Python包含6种内建序列:列表.元组.字符串.Unicode字符串.buffer对象.xrange对象. 这些序列支持通用的操作: 索引 索引是从0开始计数:当索引值为负数时,表示从最后一个元素( ...
- Python通用序列操作
1.序列概览 1.数据结构 序列.容器 Python中最基本的数据结构是序列,其有索引(从左到右第一个索引为0,从右到左第一个索引为-1). Python包含6中内建的序列: 列表 元组 字符串 Un ...
随机推荐
- 修改IDEA默认模板
然后找到你想要修改的模板就可以了
- Element form表单方法resetFields无效
之前遇到resetFields无效时都是自己手动用this.ruleForm = Object.assign({}, this.ruleForm, this.$options.data().ruleF ...
- Learning ROS: Packaging your ROS project as a snap
Snaps are containerised software packages that are simple to create and install. They auto-update an ...
- ubantu上面 NFS服务器安装
---恢复内容开始--- N月一更............ 本博客部分参照:https://blog.csdn.net/CSDN_duomaomao/article/details/77822883 ...
- spring boot 系列之八:SpringBoot处理定时任务
项目经常会用到定时任务,springboot自然是可以通过整合相关组件来实现的. 目前常用的定时任务的实现有两种: 通过spring 自带的定时器任务@Schedule来实现 通过Quartz来实现 ...
- 命令行解析函数:getopt_long、getopt
一.前言 在学习一些项目代码时,尤其涉及到命令行传参的代码,经常遇到getopt相关的函数,对这一类函数可以说是既陌生又熟悉.陌生是因为不知道它是干啥的,熟悉呢,是因为经常遇到.于是乎在追踪了多天ip ...
- mac、ip、udp头解析
一.MAC帧头定义 /*数据帧定义,头14个字节,尾4个字节*/ typedef struct _MAC_FRAME_HEADER { char m_cDstMacAddress[6]; // ...
- io流-文件流\节点流
FileOutputStream类(jdk1.0) 描述 java.io.FileOutputStream 类是文件字节输出流,用于将数据写入到文件中. 构造方法 //构造方法 FileOutputS ...
- Dart简易教程 (1)---数据类型 运算符,类转换换
从下面开始学习DART编程 以下是一个简单的示例: main(){ var number = 42; print(number);}程序说明,dart是一个强大的脚本类语言,可以不预先定义变量类型 , ...
- CodeForce-813B The Golden Age(数学+枚举)
The Golden Age CodeForces - 813B 题目大意:如果一个数t=x^a+y^b(a,b都是大于等于0的整数)那就是一个unlucky数字.给你x,y,l,r(2 ≤ x, y ...