元组拆分
元组拆分是最为常见的一种拆分,示例如下:
1
2
3
|
p = ( 4 , 5 )
x, y = p
print (x, y) # 4 5
|
如果写成
1
|
x, y, z = p
|
那么就会抛出ValueError异常:“not enough values to unpack (expected 3, got 2)”
如果写成
1
2
|
p = ( 4 , 5 , 6 )
x, y = p
|
那么就会抛出ValueError异常:“too many values to unpack (expected 2)”
字符串拆分
字符串的拆分示意如下:
1
2
3
|
s = 'Hello'
a, b, c, d, e = s
print (a) # H
|
拆分时丢弃值
如果在拆分时想丢弃某些特定的值,可以用一个用不到的变量名来作为丢弃值的名称(常选'_'做为变量名),如下所示:
1
2
3
|
s = 'Hello'
a, b, _, d, _ = s
print (a) # H
|
嵌套序列拆分
Python也提供简洁的对嵌套序列进行拆分的语法。如下所示我们对一个比较复杂的异质列表进行拆分:
1
2
3
|
data = [ 'zhy' , 50 , 123.0 , ( 2000 , 12 , 21 )]
name, shares, price, (year, month, day) = data
print (year) # 2000
|
如果你想完整地得到(2000, 12, 21)这个表示时间戳的元组,那么你就得这样写:
1
2
3
|
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"。针对这个问题的解决方案是采用"*"表达式。
比如我们给定学生的分数,想去掉一个最高分和一个最低分,然后对剩下的学生求平均分,我们可以这样写:
1
2
3
4
5
6
7
|
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
|
还有一种情况是有一些用户记录,记录由姓名+电子邮件+任意数量的电话号码组成,则我们可以这样分解用户记录:
1
2
3
|
record = [ 'zhy' , 'zhy1056692290@qq.com' , '773-556234' , '774-223333' ]
name, email, * phone_numbers = record
print (phone_numbers) # ['773-556234', '774-223333']
|
事实上,如果电话号码为空也是合法的,此时phone_numbers为空列表。
1
2
3
|
record = [ 'zhy' , 'zhy1056692290@qq.com' ]
name, email, * phone_numbers = record
print (phone_numbers) # []
|
还有一种使用情况则更为巧妙。如果我们需要遍历变长元组组成的列表,这些元组长度不一。那么此时*表达式可大大简化我们的代码。
1
2
3
4
5
|
records = [( 'foo' , 1 , 2 ), ( 'bar' , 'hello' ), ( 'foo' , 3 , 4 )]
for tag, * args in records:
if tag = = 'bar' :
print (args)
# ['hello']
|
在对一些复杂的字符串进行拆分时,*表达式也显得特别有用。
1
2
3
|
line = "nobody:*:-2:-2:-2:Unprivileged User:/var/empty:/usr/bin/false"
uname, * fields, home_dir, sh = line.split( ':' )
print (home_dir) # /var/empty
|
*表达式也可以和我们前面说的嵌套拆分和变量丢弃一起结合使用。
1
2
3
|
record = [ 'ACME' , 50 , 123.45 , ( 128 , 18 , 2012 )]
name, * _, ( * _, year) = record
print (year) # 2012
|
最后再介绍*表达式用于递归函数的一种黑魔法,比如与递归求和结合可以这样写:
1
2
3
4
5
|
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. 数学是符号的艺术,音乐是上界的语言。
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注服务器之家的更多内容!
原文链接:https://www.cnblogs.com/lonelyprince7/p/15383250.html