*表达式 解决too many values to unpack的异常
假设有24个成绩,去头掐尾
python
# 定义一个函数,用于去掉列表中的第一个和最后一个元素,并返回剩余元素的平均值
def drop_first_last(grades):
# 使用解包的方式,将列表中的第一个元素赋值给变量first,
#剩余元素赋值给变量middle,
# 最后一个元素赋值给变量last
first, *middle, last = grades
# 返回剩余元素的平均值
return avg(middle)
假设有一些用户数据,附带任意数量的电话号码
ini
# 定义一个元组record,包含四个元素
record = ('Dave', '[email protected]', '773-555-1212', '847-555-1212')
# 使用*phone_numbers将元组record中的前两个元素赋值给name和email,剩余的元素赋值给phone_numbers
name, email, *phone_numbers = record
# 打印phone_numbers
print(phone_numbers)
假设要让最后的一个季度的销售额和前面几个季度的均值作对比
ini
# 计算过去四季度销售额的平均值
*trailing_qtr = sales_record
# 计算过去四季度销售额的总和
trailing_avg = sum(trailing_qtr) / len(trailing_qtr)
# 返回与当前季度销售额的比较结果
return avg_comparison(trailing_avg, current_qtr)
星号在变量名前的意思是,这个变量将接收解包后的所有剩余元素。换句话说,如果 sales_record
是一个包含四个元素的列表,那么 trailing_qtr
将会是一个包含前三个元素的列表,而第四个元素将被赋值给 trailing_qtr
。
例如:
ini
sales_record = [10, 20, 30, 40]
*trailing_qtr, last_qtr = sales_record
在这个例子中,trailing_qtr
将会是 [10, 20, 30]
,而 last_qtr
将会是 40
。
需要注意的是,这种解包语法要求左侧的变量数量不能超过可迭代对象的元素数量。如果 sales_record
只包含三个元素,那么上述代码将会引发 ValueError
,因为左侧有四个变量(包括 *trailing_qtr
中的三个元素和 last_qtr
)。
此外,*trailing_qtr
这种用法在赋值语句的左侧是Python 3.0引入的。在Python 2.x中,这种语法是不支持的。
假设有一个带标记的元组:
python
record = [('foo', 1, 2),
('bar', 'hello'),
('foo', 3, 4)]
# 定义一个函数,参数为x和y,打印出'foo'和x、y的值
def do_foo(x, y):
print('foo', x, y)
# 定义一个函数,参数为s,打印出'bar'和s的值
def do_bar(s):
print('bar', s)
# 遍历record列表,tag为record中的第一个元素,args为record中的剩余元素
for tag, *args in record:
# 如果tag为'foo',则调用do_foo函数,并传入args中的参数
if tag == 'foo':
do_foo(*args)
# 如果tag为'bar',则调用do_bar函数,并传入args中的参数
elif tag == 'bar':
do_bar(*args)
split拆分
bash
# 定义一个字符串变量line,包含一个用户信息
line = 'nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false'
# 使用split()方法将字符串按照冒号分割,得到一个列表
uname, *fields, homedir, sh = line.split(':')
print(uname)
print(fields)
print(homedir)
print(sh)
拆分后丢弃
scss
record = ('ACME', 50, 123.45, (12, 18, 2023))
name, *_, (*_, year) = record
print(name)
print(year)
print(record)
头尾分离
bash
# 定义一个列表items,包含6个元素
items = [1, 10, 7, 4, 5, 9]
# 使用解包操作符*,将列表items的第一个元素赋值给head,剩余的元素赋值给tail
head, *tail = items
# 打印head的值
print(head)
# 打印tail的值
print(tail)
# 使用解包操作符*,将tail中的元素依次打印出来
print(*tail)
应用递归
bash
# 定义一个函数sum,参数为items
def sum(items):
# 将items列表拆分为head和tail两部分,head为列表的第一个元素,tail为剩余的元素
head, *tail = items
# 如果tail不为空,则递归调用sum函数,将tail作为参数传入,并将head和递归调用的结果相加
# 如果tail为空,则返回head
return head + sum(tail) if tail else head
-
这行代码是递归的核心部分:
- 如果
tail
不为空(即列表中还有元素),则递归调用sum
函数,将tail
作为参数传入,并将head
和递归调用的结果相加。 - 如果
tail
为空(即列表中只有一个元素),则直接返回head
。
- 如果
实现原理
这个函数通过递归的方式不断地将列表拆分为第一个元素和剩余的元素,然后将第一个元素与剩余元素的总和相加,直到列表中只剩下一个元素为止。
用途
这个函数可以用来计算一个列表中所有元素的总和。例如,sum([1, 2, 3, 4])
将返回 10
。
注意事项
- 输入类型 :这个函数假设输入的
items
是一个列表。如果传入的不是列表,代码会抛出错误。 - 空列表 :如果传入一个空列表,这个函数会抛出错误,因为
head
会尝试访问列表的第一个元素,但列表是空的。 - 性能:对于非常大的列表,这种递归方式可能会导致性能问题,因为递归调用会增加调用栈的深度。
改进
为了处理空列表的情况,可以在函数开始时添加一个检查:
bash
Python
复制 插入 新文件
def sum(items):
if not items:
return 0
head, *tail = items
return head + sum(tail) if tail else head
这样,如果传入的是空列表,函数将返回 0
。