引言
尽管列表和元祖没有直接的关系,但是在操作上,元祖可以被当做列表的只读版本,倔强的是 他不可修改
1.元祖概述
In [4]: a = tuple([1,'abc'])
In [5]: a[0] =1
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
in
----> 1 a[0] =1
TypeError: 'tuple' object does not support item assignment
元祖只用小括号语法,但是要和普通的小括号区别开
In [14]: a = (1,) #只有一个元素的元祖
In [15]: type(a)
Out[15]: tuple
In [16]: a = (1) # 普通括号
In [17]: type(a)
Out[17]: int
因为元祖是不可变类型,他的指针数组无序变动,故以此行完成内存分配,系统缓存复用一定长度的元祖内存(包涵指针数组).创建时,所需要的长度提取复用,没有额外的内存分配,从这点来看,元祖的性能要好于列表.
Python3.6 缓存复用长度在20以内的tuplen内存,每种2000上限
对于性能的测试
In [21]: %timeit (1,2,3) # tuple
82 ns ± 23.6 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [22]: %timeit [1,2,3] # list
738 ns ± 60.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
可以看出,.列表比tuple占用的时间相对来说要多
2.支持与列表类似的运算符操作,但是不能修改,总是返回新的对象
In [24]: (1, 2) + (3, 4)
Out[24]: (1, 2, 3, 4)
In [25]: (1, 2) * 2
Out[25]: (1, 2, 1, 2)
In [26]: a = (1, 2, 3)
In [27]: b =a
In [28]: a +=(4, 5) # 创建新的tuple,而不是修改原来的内容
In [29]: a
Out[29]: (1, 2, 3, 4, 5)
In [30]: b
Out[30]: (1, 2, 3)
3.namedtuple,tuple的高阶用法
因为列表支持插入,删除,等修改操作,所以序号无法与元素对象对象构成固定映射.但是元祖不同,相同的序号总是返回同一对象,故可以基于序号起一个"别名"
In [39]: import collections # 导入
In [40]: User = collections.namedtuple("User","name,age") # 创建User类型,执行字段
In [41]: issubclass(User,tuple) # Tuple子类
Out[41]: True
In [42]: u.name,u.age # 使用字段名访问
Out[42]: ('qpython', 66)
In [43]: u[0] is u.name # 或者依旧使用序号
Out[43]: True
和定义纯数据类型,显然namedtuple要比class简洁,关键在于,名字比序号更容易阅读和更容易维护,其类似于数字常量定义.