你真的了解Python的元组吗?
2017-09-25 本文已影响0人
万越天
这一篇是《流畅的 python》读书笔记。
1 元组
在有些python的介绍中,元组被称为不可变列表
,这其实是不准确的,没有完全概括元组的特点。元组除了用作不可变列表,还可以用于没有字段名的记录
。
1.1 元组和记录
元组其实是对数据的记录:元组中的每个元素都存放了记录中一个字段的数据,外加这个数据的位置。
如果把元组当作一些字段的集合,数量和位置信息会变得非常重要。比如以下几条用元组表示的记录:
# 洛杉矶国际机场的经纬度
>>> lax_coordinates = (33.9425, -118.408056)
# 东京的一些信息:市名、年份、人口、人口变化和面积
>>> city, year, pop, chg, area = ('Tokyo', 2003, 32450, 0.66, 8014)
以上这两个元组每个位置都对应一个数据记录。
1.2 元组拆包
>>> city, year, pop, chg, area = ('Tokyo', 2003, 32450, 0.66, 8014)
这个例子中,我们把元组的数据用一条语句分别赋值给 city, year, pop, chg, area,这就是元组拆包的一个具体应用。
元组拆包可以应用到任何可迭代对象上,但是被迭代的对象窄的元素的数量必须跟接受这些元素的元组的空档数一致。
>>> lax_coordinates = (33.9425, -118.408056)
>>> latitude, longitude = lax_coordinates
>>> latitude
33.9425
>>> longitude
-118.408056
还可以用*
运算符把一个可迭代对象拆开作为函数的参数:
>>> divmod(20, 8)
(2, 4)
>>> t = (20, 8)
>>> divmod(*t)
(2, 4)
>>> quotient, remainder = divmod(*t)
>>> quotient, remainder
(2, 4)
在进行拆包是,我们可能对元组的某些值并不感兴趣,这时可以用_
占位符处理。比如:
>>> divmod(20, 8)
(2, 4)
>>> _, remainder = divmod(20, 8)
>>> _
2
>>> remainder
4
在处理函数参数时,我们经常用*args
来表示不确定数量的参数。在python3中,这个概念被扩展到了平行赋值中:
>>> a, b, *rest = range(5)
>>> a, b, rest
(0, 1, [2, 3, 4])
>>> a, *rest, c, d = range(5)
>>> a, rest, c, d
(0, [1, 2], 3, 4)
>>> a, b, *rest = range(2)
>>> a, b, rest
(0, 1, [])
元组也支持嵌套拆包,比如:
>>> l = (1, 2, 3, (4, 5))
>>> a, b, c, (d, e) = l
>>> d
4
>>> e
5
1.3 具名元组
元组作为记录除了位置以外还少一个功能,那就是无法给字段命名,namedtuple
解决了这个问题。
namedtuple 使用方式实例:
>>> from collections import namedtuple
>>> city = namedtuple('City', 'name country population coordinates')
>>> tokyo = city('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
>>> tokyo.population
36.933
>>> tokyo[1]
'JP'
>>> city._fields
('name', 'country', 'population', 'coordinates')
>>> tokyo_data = ('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
>>> tokyo = city._make(tokyo_data)
>>> tokyo._asdict()
OrderedDict([('name', 'Tokyo'), ('country', 'JP'), ('population', 36.933), ('coordinates', (35.689722, 139.691667))])
collections.namedtuple 是一个工厂函数,它可以用来构建一个带字段名的元组和一个有名字的类。 namedtuple 构建的类的实例锁消耗的内存和元组是一样的,因为字段名都被存放在对应的类里。这个实例和普通的对象实例相比也更小一些,因为 在这个实例中,Python 不需要用 __dict__ 来存放这些实例的属性