Tuple是Python内置的另一种数据类型,元组。Tuple也是一种有序的集合,tuple和list非常类似,但是tuple一旦初始化就不能修改。
比如:同样是列出同学的名字,如下:
>>> classmates = ('Bob', 'Tract', 'Jack')
>>> classmates
('Bob', 'Tract', 'Jack')
现在,classmates这个tuple不能变了,它也没有append(),insert()这样的方法。其他获取元素的方法和list是一样的,你可以正常地使用classmates[0] , classmates[-1] ,但不能赋值成另外的元素。如下:
>> classmates = ('Bob', 'Tract', 'Jack')
>>> classmates
('Bob', 'Tract', 'Jack')
>>> classmates[0]
'Bob'
>>> classmates.append('Judy')
Traceback (most recent call last):
File "<pyshell#61>", line 1, in <module>
classmates.append('Judy')
AttributeError: 'tuple' object has no attribute 'append'
>>> classmates.insert(1, 'Judy')
Traceback (most recent call last):
File "<pyshell#62>", line 1, in <module>
classmates.insert(1, 'Judy')
AttributeError: 'tuple' object has no attribute 'insert'
注意: 当定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来。如:
>>> t = (1, 2)
>>> t
(1, 2)
1. 新建元组
t1 = ('Python','123',111)
print(t1)
打印结果:
如果新建时没有用( )括号括起来,只用逗号进行分隔,python也会把它认做为元组,如:
t2 = 'Python','123',111
print(t2)
打印结果:
如果新建元组中只有一个值,那么请记得在这个值后边加上逗号,如果没有逗号,python只当把它当做整型来处理。
如:
t3 = 1,
t4 = (1,)
t5 = 1
t6 = (1)
print("t3和t4: ", t3, t4)
print("t5和t6: ", t5, t6)
打印结果:
新建空元组如下:
t7 = ()
print(t7)
打印结果:
2. 将列表转换为元组
要将列表或字符串转换为元组,用到元组函数tuple()即可,如:
list = [1, 2, 'python']
str = 'String'
t8 = tuple(list) # 括号里的是列表
t9 = tuple(str) # 括号里的是字符串
print(t8)
print(t9)
打印结果:
3. 获取元组中的数据
t = (1,2,3,4,5)
print("第1个元素:", t[0])
print("第2个元素:", t[1])
打印结果:
4. 元组的index()函数
元组 index() 方法用于从元祖中找出某个对象第一个匹配项的索引位置,如果这个对象不在元祖中会报一个异常。
index() 方法:
t.index(obj[,start=0[,end=len(T)]])
参数说明:
- obj – 指定检索的对象。
- start – 可选参数,开始索引,默认为0。(可单独指定)
- end – 可选参数,结束索引,默认为元祖的长度。(不能单独指定)
t = ('x', 'y', 1, 'x', 2, 'x')
print(t.index('x'))
print(t.index('x', 1))
print(t.index('x', 4))
print(t.index('y'))
print(t.index('y', 2))
打印结果:
说明:
最后的报错,是因为从索引位置2开始向后,不存在’y’元素了,所以保存在的异常。
5. 元组的count()函数
元组 count() 方法用于统计某个元素在元祖中出现的次数。
count() 方法:
t.count(obj)
参数说明:
- obj – 元祖中统计的对象。
t = (123, 'Google', '123', 'Taobao', 'xyz', 123)
print("123 元素个数 : ", t.count(123))
print("'678' 元素个数 : ", t.count('678'))
print("'Taobao' 元素个数 : ", t.count('Taobao'))
打印结果:
6. 元组的相对不可变性(转自: Python 元组的相对不可变性)
Python中的元组是一种类似于列表的容器类型,但列表是可变的而元组是不可变。
元组本身是不可变的,但是它所包含的元素的可变性取决于该元素的属性。
首先来看一个问题:
>>> t = (1, 2, [30, 40])
>>> t[2] += [50, 60]
以上两个表达式到底会发生下面 4 种情况下的哪一种?
- t 变成 (1, 2, [30, 40, 50, 60])。
- 因为 tuple 不支持对它的元素赋值,所以会抛出 TypeError 因为 tuple 不支持对它的元素赋值,所以会抛出 TypeError 异常。
- 以上两个都不是。
- 1 和 2 都是对的。
刚看到上面的问题,可能正常的大多数人会选1,也有可能会选2。
但结果究竟是啥呢?我们运行一下,看一下结果如何:
>>> t = (1, 2, [30, 40])
>>> t[2] += [50, 60]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> t
(1, 2, [30, 40, 50, 60])
看到上面的运行结果,其实答案就一目了然了, 自然4是正确答案了。
6.1 变量不是盒子
在回答这个问题之前我们来了解 Python 中的变量。
“变量是盒子”这样的比喻经常被使用,但是这有碍于理解面向对象语言中的引入式变量。如下所示的交互式控制台中,无法使用“变量是盒子”做解释。
>>> a = [1, 2, 3]
>>> b = a
>>> a.append(4)
>>> b
[1, 2, 3, 4]
如果把变量想象为盒子,那么无法解释 Python 中的赋值。Python 变量类似于 Java 中的引用式变量,因此最好把它们理解为附加在对象上的标注。
为了理解 Python 中的赋值语句,应该始终先读右边(对引用式变量来说,说把变量分配给对象更合理。毕竟,对象在赋值之前就创建了。)。对象在右边创建或获取,在此之后左边的变量才会绑定到对象上,这就像为对象贴上标注。
6.2 元组不可变性指的是?
元组与多数 Python 集合(列表、字典、集,等等)一样,保存的是对象的引用。如果引用的元素是可变的,及时元组本身不可变,元素依然可变。也就是说,元组的不可变性其实指 tuple 数据结构的物理内容(即保存的引用)不可变,与引用的对象无关。
我们看一下示例:
>>> t = (1, 2, [30, 40])
>>> id(t[-1]) # 查看t[-1]的标识
17159496
>>> t[-1].append(99)
>>> t
(1, 2, [30, 40, 99])
>>> id(t[-1])
17159496
我们看到:查看 t[-1] 列表的标识可以看到标识没变,只是值变了。
回到最初的问题,如果写成如下代码:
>>> t = (1, 2, [30, 40])
>>> t[2].extend([50, 60])
>>> t
(1, 2, [30, 40, 50, 60])
我们发现就可以避免异常。
因此,引发异常的操作在于对不可变元组的元素进行了赋值。这也对前面所说的变量是标注作了很好的注释。在分配给变量前对象就已经创建,所以尽管后来的赋值操作引发了异常,列表对象还是发生了变化。