2.3 元组不仅仅是不可变的列表
除了用作不可变的列表,元组还可以用于没有字段名的记录。
元组其实是对数据的记录:元组中的每个元素都存放了记录中一个字段的数据,外加这个
字段的位置。正是这个位置信息给数据赋予了意义。如果把元组当作一些字段的集合,那么数量和位置信息就
变得非常重要了。
元组用作记录
# 示例2-7 把元组用作记录
# 洛杉矶国际机场的经纬度。
lax_coordinates = (33.9425, -118.408056)
# 东京市的一些信息:市名、年份、人口(单位:百万)、人口变化(单位:百分比)
# 和面积(单位:平方千米)。将元组中的每一个元素 赋值给一个变量,给予它特定的含义
# 这就称为元组的拆包
city, year, pop, chg, area = ('Tokyo', 2003, 32450, 0.66, 8014)
# 一个元组列表,元组的形式为 (country_code, passport_number)
traveler_ids = [
('USA', '31195855'),
('BRA', 'CE342567'),
('ESP', 'XDA205856')
]
# 在迭代的过程中,passport 变量被绑定到每个元组上
for passport in sorted(traveler_ids):
# % 格式运算符能被匹配到对应的元组元素上。
# 一个 % 运算符就把 passport 元组里的元素对应到了 print 函数
# 的格式字符串空档中,这也是元组拆包的应用
print('%s / %s' % passport)
# for 循环可以分别提取元组里的元素,也叫作拆包(unpacking)。因为元组中第二个
# 元素对我们没有什么用,所以它赋值给“_”占位符。
# 拆包让元组可以完美地被当作记录来使用
for country, _ in traveler_ids:
print(country)
元组拆包
元组拆包可以应用到任何可迭代对象上,唯一的硬性要求是,被可迭代对象中
的元素数量必须要跟接受这些元素的元组的空档数一致
最好辨认的元组拆包形式就是平行赋值,也就是说把一个可迭代对象里的元素,一并赋
值到由对应的变量组成的元组中。
比如优雅的不使用中间变量交换两个变量的值的方法
b , a = a , b
#元组拆包范例
lax_coordinates = (33.9425, -118.408056)
# 平行赋值将元组拆包
latitude, longitude = lax_coordinates;
print(latitude)
# 33.9425
print(longitude)
# -118.408056
# python divmod() 函数把除数和余数运算结果结合起来,
# 返回一个包含商和余数的元组(a // b, a % b)
d = divmod(20, 8)
print(d)
# (2, 4)
# 用 * 运算符把一个可迭代对象拆开作为函数的参数:
t = (20, 8)
result = divmod(*t)
print(t)
# (2, 4)
quotient, remainder = divmod(*t)
print(quotient)
# 2
print(remainder)
# 4
import os
# os.path.split("/home/shuaibi/niupi/idrsa.pub")该函数返回
# 以路径和最后一个文件名组成的元组
# 会打印('/home/shuaibi/niupi', 'idrsa.pub')
print(os.path.split("/home/shuaibi/niupi/idrsa.pub"))
# 使用元组拆包则会轻松的只拿到 最后一个文件的文件名
_, filename = os.path.split("/home/shuaibi/niupi/idrsa.pub")
# "_"占位符能够处理掉前面的文件路径
print(_) # 实际上,这个占位符还是保存着这个路径变量的 /home/shuaibi/niupi
# /home/shuaibi/niupi
print(filename)
# idrsa.pub
# 在元组拆包中使用*来处理剩下的元素
a, b , *rest = range(5)
print(a,b,rest)
# 0 1 [2, 3, 4]
a,b,*rest = range(3)
print(a,b,rest)
# 0 1 [2]
a,b,*rest = range(2)
print(a,b,*rest)
# 此处和书中的结果并不一样 在pycharm中这样执行 打印0 1 rest并不会显示
# 在命令行中 执行结果和书中相同
# >>> a,b,*rest = range(2)
# >>> a,b,rest
# (0, 1, [])
c = []
print(c)
# 但是 自定义个空列表的话是可以打印出来的 [] pycharm这个执行的机制
# 具体是怎么回事,弱鸡的我是真的不知道。希望有朝一日有大佬能够看到
# 这篇文章 给我指点一下子
# 言归正传
# 在平行赋值中,* 前缀只能用在一个变量名前面,但是这个变量可以出现在赋值表达式的
# 任意位置
a, *body, c, d = range(5)
print(a, body, c, d)
# 0 [1, 2] 3 4
*head, b, c, d = range(5)
print(head, b, c, d)
# [0, 1] 2 3 4
具名元组
collections.namedtuple 是一个工厂函数,它可以用来构建一个带字段名的元组和一
个有名字的类——这个带名字的类对调试程序有很大帮助
用 namedtuple 构建的类的实例所消耗的内存跟元组是一样的,因为字段名都
被存在对应的类里面。这个实例跟普通的对象实例比起来也要小一些,因为 Python
不会用 dict 来存放这些实例的属性
# 展示如何使用用具名元组来记录一个城市的信息
from collections import namedtuple
# 创建一个具名元组需要两个参数,一个是类名,另一个是类的各个字段的名字。后者
# 可以是由数个字符串组成的可迭代对象,或者是由空格分隔开的字段名组成的字符串。
City = namedtuple('City', 'name country population coordinates')
# 存放在对应字段里的数据要以一串参数的形式传入到构造函数中(注意,元组的构造
# 函数却只接受单一的可迭代对象)
# name country population coordinates
tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
print(tokyo)
# City(name='Tokyo', country='JP', population=36.933, coordinates=(35.689722, 139.691667))
# 可以通过字段名或者位置来获取一个字段的信息
print(tokyo.population)
# 36.933
print(tokyo.coordinates)
# (35.689722, 139.691667)
print(tokyo[0])
# Tokyo
print(tokyo[1])
# JP
# _fields 属性是一个包含这个类所有字段名称的元组。
print(City._fields)
# ('name', 'country', 'population', 'coordinates')
# 又创建一个nametuple 稍后初始化为具体对象并当作参数传入
LatLong = namedtuple("LatLong", "lat long")
# 创建一个数据集合
delhi_data = ("Delhi NRC", "IN", 21.935, LatLong(28.613889, 77.208889))
# 通过数据集合 新建一个城市对象
# 用 _make() 通过接受一个可迭代对象来生成这个类的一个实例,它的作用跟
# City(*delhi_data) 是一样的
delhi = City._make(delhi_data)
# _asdict() 把具名元组以 collections.OrderedDict 的形式返回,我们可以利用它
# 来把元组里的信息友好地呈现出来
delhi_datas = delhi._asdict()
print(delhi_datas)
# OrderedDict([('name', 'Delhi NRC'), ('country', 'IN')
# , ('population', 21.935), ('coordinates', LatLong(lat=28.613889, long=77.208889))])
for key, value in delhi._asdict().items():
print(key + ' : ', value)
# name : Delhi NRC
# country : IN
# population : 21.935
# coordinates : LatLong(lat=28.613889, long=77.208889)
元组不仅可以当作记录用的数据类型,而且也可以充当一个不可变的列表
作为不可变列表的元组
首先 看一下书中的一个元组与列表的对比表
除了跟增减元素相关的方法外 元组支持列表的其他所有的方法
小结
掌握拆包的方法,这本书中的很多代码都是比较。。。怎么说 很Python的风格的代码
不带一点方言。。。所以 对于我这种基础不扎实的 需要好好理解。就比如那个format的规则,
平时不经常用,研究了一会才知道怎么运作的。 另外就是自己对于nametuple的使用感受,
可以当作一个C的结构体类似的东西使用,(又带方言了。。)到现在我感觉自己学的
很散乱一样,可能这本书确实面向大佬,慢慢来吧。 好吧 大概就这些