- 2.1序列
常见序列:list、tuple、array、deque
分类:
(1)容器序列和扁平序列:容器序列存放的是所包含对象的引用,对象可以是任何类型。扁平序列存储所含内容的值。
容器序列包括:list、tuple、collection.deque
扁平序列包括:str、bytes、array.array
(2)可变序列和不可变序列:可变序列继承不可变序列所有方法。
可变序列: list、bytearray、array.array、collection.deque
不可变序列:tuple、str、bytes
- 2.2 列表推导式(list comprehension)和生成器表达式(generator expression)
(1)列表推导式
列表推导式应当简洁,一般不超过两行。
tips:跨多行定义列表,在每一行最后多加一个逗号。易读易改。
symbols = '@#¥%&*'
codes = [ord(symbol) for symbol in symbols]
>>>codes
[64, 35, 65509, 37, 38, 42]
(2)笛卡尔积
使用列表推导式可以快速生成有两个属性的列表。
colors = ['black','white']
sizes = ['L','M','L']
shirts = [(color,size) for color in colors
for size in sizes]
>>> shirts
[('black', 'L'),
('black', 'M'),
('black', 'L'),
('white', 'L'),
('white', 'M'),
('white', 'L')]
(3)生成器表达式
生成及表达式句法与列表推导式一致,只需要将[]改为()。生成器表达式使用迭代器逐个产出项。
symbols = '@#¥%&*'
tuple(ord(symbol) for symbol in symbols)
>>>tuple
(64, 35, 65509, 37, 38, 42)
colors = ['black','white']
sizes = ['L','M','L']
for tshirt in (f'{c}{s}' for c in colors for s in sizes)
print (tshirt)
- 2.3 元组的记录和不可变列表作用
基本用法见站内博客:Python 之元组(tuple)_元组的特点_Water_Coder的博客-CSDN博客
(1)用作记录
元组存放记录,一项对应一个字段的数据,项的位置决定数据的意义。
lax = (33.9425,-118.408056)
city,year,pop,chg,area=('Tokyo',2003,32_450,0.66,8014)
traveler_ids=[('USA','311195855'),('BRA','CE342657'),
('ESP','XDA2345')]
for passport in sorted (traveler_ids):
print('%s/%s' % passport)
>>>BRA/CE342657
ESP/XDA2345
USA/311195855
for country,_ in traveler_ids:
print (country)
>>>USA
BRA
ESP
迭代的过程中,passport变量被绑定到每个元组上,逐个输出。
我们对元组的第二项不感兴趣,因此被赋值给_,_是一个虚拟变量。
(2)用作不可变列表
优点:意图清晰——源码中的元组长度永不可变;性能优越——占用内存少。
注:元组的不可变仅针对元组中的引用而言,指元组的引用始终指向一个对象。若元组引用了一个可变对象,当该对象中的内容改变时,元组中的值也会随之变化。
a = (10,'alpha',[1,2])
b = (10,'alpha',[1,2])
a == b
>>> True
b[-1].append(99)
a == b
>>> False
可用hash函数定义一个函数检测元组内部引用是否可变。
def fixed(o):
try:
hash(o)
except TypeError:
return False
return True
tf = (10,'alpha',(1,2))
tm = (10,'alpha',[1,2])
fixed(tf)
fixed(tm)
>>>fixed(tf)
True
>>>fixed(tm)
False
- 2.4 序列和可迭代对象拆包
拆包:不需要手动通过索引获取元素。目标可以是任何可迭代对象,要求是一次只能产出一项给接收端变量,或者用*捕获余下的项。
并行赋值:把可迭代对象中的项赋值给变量元组。
(1)用 * 捕获余下的项
a,b,*rest = range(1,5)
a,b,rest
>>>(1, 2, [3, 4])
并行赋值时,* 前缀只能应用到一个变量上。
a, *body , c ,d = range(5)
a, body , c ,d
>>>(0, [1, 2], 3, 4)
(2)在函数调用和序列字面量中使用 * 拆包
def fun(a,b,c,d,*rest):
return a,b,c,d,rest
fun(*[1,2],3,*range(4,7))
>>>(1, 2, 3, 4, (5, 6))
(3)嵌套拆包
metro_areas = [
('Tokyo', 'JP', 36.933, (35.689722, 139.691667)), # <1>
('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),
('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),
('São Paulo', 'BR', 19.649, (-23.547778, -46.635833)),
]
def main():
print(f'{"":15} | {"latitude":>9} | {"longitude":>9}')
for name, _, _, (lat, lon) in metro_areas: # <2>
if lon <= 0: # <3>
print(f'{name:15} | {lat:9.4f} | {lon:9.4f}')
if __name__ == '__main__':
main()
>>> main()
| latitude | longitude
Mexico City | 19.4333 | -99.1333
New York-Newark | 40.8086 | -74.0204
São Paulo | -23.5478 | -46.6358
<1>:每个元组四个字段
<2>:最后一个字段赋值给一个嵌套元组
<3>:选取条件
拆包赋值的对象也可以是一个列表。