Python Cookbook 之一 数据结构和算法(二): 从任意长度的可迭代对象中分解元素

本文介绍如何使用Python的*表达式从不定长的可迭代对象中分解元素,包括*表达式位于首位、中间和末位的不同应用场景,以及在字符串处理和元组序列迭代中的实用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

欢迎大家扫码关注我的微信公众号:
数据之恋

一、问题

需要从某个可迭代对象中分解出 N 个元素, 但是这个可迭代对象的长度可能超过 N, 这会导致出现 “分解值过多(too many values to unpack)” 的异常。

二、解决方案

Python 的 “* 表达式” 可以用来解决这个问题。 且它可以出现在任意位置。

2.1 * 表达式在首位

需求: 有一个未知长度的列表, 其内均为 int 型元素。 现需要求出最后一个元素之前的所有元素的平均值与最后一个元素的差值。
解决:

>>> *a, c = [1, 2, 3]
>>> b = sum(a) / len(a)
>>> b - c
-1.5

2.2 * 表达式在中间

需求:有一个未知长度的列表, 其内均为 int 型元素。 现需求出除第一个和最后一个元素之外其余所有元素的平均值。
解决:

>>> a, *b, c = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> sum(b) / len(b)
5.0

2.3 * 表达式在末位

需求: 有一个未知长度的列表, 其内第一个元素是学生姓名, 第二个元素是性别, 从第三个开始是他的考试成绩(不定长)。 现需要将该学生的所有成绩取出来。
解决:

>>> name, sex, *scores = ['Cybeyond', 'Male', 99, 100, 89, 92, 97]
>>> name
'Cybeyond'
>>> sex
'Male'
>>> scores
[99, 100, 89, 92, 97]

三、讨论

对于分解未知长度的可迭代对象, 利用 * 表达式使得开发者可以轻松地得到所关心的元素, 而不必在可迭代对象中做复杂花哨的操作。

*表达式在迭代一个变长的元组序列时尤其有用:

>>> lst = [('foo', 1, 2), ('bar', 'aa'), ('foo', 3, 4), ('bar', 'bb')]
>>>
>>> def do_foo(x, y):
...     print('foo', x, y)
... 
>>> 
>>> def do_bar(s):
...     print('bar', s)
... 
>>> 
>>> for tag, *args in lst:
...     if tag == 'foo':
...         do_foo(*args)
...     elif tag == 'bar':
...         do_bar(*args)
... 
foo 1 2
bar aa
foo 3 4
bar bb

当和某些特定的字符串处理操作相结合, 比如拆分操作时:

>>> url = 'https://127.0.0.1:8080/rest/get_data/?id=4&tag=cybeyond&name=xuan'
>>> _, tag_requirement, name_requirement = url.split('&')
>>> tag_requirement
'tag=cybeyond'
>>> name_requirement
'name=xuan'

可以使用几个常用来表示丢弃值的变量名来承接想要丢弃的值, 如 _ 或 ign(ignore):

>>> name, _, *scores = ['Cybeyond', 'Male', 99, 100, 89, 92, 97]
>>> name
'Cybeyond'
>>> scores
[99, 100, 89, 92, 97]

【注意】本篇博客中所写的全部内容只能在 Python 3 版本中成功运行, 在 Python 2 版本中将会报 SyntaxError: invalid syntax 异常!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值