元组(tuple)也是Python中的一种对象类型,它与之前讲的列表、字符串、整数等并列。但因为它与列表很相似,所以容易被忽略或混淆。
定义
>>> t1 = ('123','abc',True,456)
>>> t1
('123', 'abc', True, 456)
>>> t2 = 'a','b',1,['c',2]
>>> t2
('a', 'b', 1, ['c', 2])
>>> type(t1)
<class 'tuple'>
>>> type(t2)
<class 'tuple'>
如上例子,t1
的定义还可以理解,但t2
竟然没有报错,而是将这些对象放到了一个圆括号里。这就是Python的元组。通过最后面的类型查看我们也可以直到,t1
和t2
都是tuple
类型。
元组是用圆括号括起来的,其中的元素之间用逗号(英文半角)隔开。元组中的元素也是任意类型的Python对象(这点与列表一样)。但有一点跟列表不同的就是元组中的元素是不能更改的,这点倒是跟字符串以及数组类似。
>>> t = (1,2,3,4)
>>> t
(1, 2, 3, 4)
>>> t[0] = 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
下面来正式的讲一下元组的创建。
创建一个空元组:
>>> tuple1 = ()
>>> type(tuple1)
<class 'tuple'>
创建带有元素的话,就跟上面的差不多,将元素包含在圆括号内以逗号隔开;注意,当创建的元组只包含一个元素时,需要在元素后面添加逗号,否则括号会被当作运算符使用:
>>> tuple2 = (10)
>>> type(tuple2)
<class 'int'>
>>> tuple3 = (10,)
>>> type(tuple3)
<class 'tuple'>
访问元组(索引&切片)
与列表跟字符串,元组同样可以使用索引和切片来进行对元素的访问,索引一样是从0开始。
>>> tup1 = ('Python','Java','C++','C')
>>> tup1[0]
'Python'
>>> tup1[1:]
('Java', 'C++', 'C')
>>> tup2 = (1,'23',[45,'abc'],('Python','Java'))
>>> tup2[2:]
([45, 'abc'], ('Python', 'Java'))
>>> tup2[2][0]
45
>>> tup2[3][0]
'Python'
修改元组
元组中的元素值是不允许修改的,但我们可以对元组进行连接组合,生成新的元组:
>>> tup1 = ('a','b')
>>> tup2 = ('c','d')
>>> tup3 = tup1 + tup2
>>> tup3
('a', 'b', 'c', 'd')
如果确实需要修改元组内的元素,我们可以将元组转为列表再对其元素进行更改。
>>> t1 = (1,2,3,4,5)
>>> lst = list(t1) # 用list()将元组转化为列表
>>> lst
[1, 2, 3, 4, 5]
>>> lst[0] = 0
>>> lst
[0, 2, 3, 4, 5]
>>> tup1 = tuple(lst) # 用tuple()将列表转化为元组
>>> tup1
(0, 2, 3, 4, 5)
删除元组
元组中的元素值是不允许删除的,但我们可以使用del
语句来删除整个元组:
>>> tup = ('Google','baidu','safari')
>>> print(tup)
('Google', 'baidu', 'safari')
>>> del tup
>>> print(tup)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'tup' is not defined
关于元组运算符、内置函数等,都与列表的差不多,这里不再赘述。
再谈元组不可变
所谓元组的不可变指的是元组内元素的指向永远不变,如何理解?看下面的例子:
>>> t = ('a','b','c',['A','B','C'])
>>> t
('a','b','c',['A','B','C'])
>>> t[3][0] = 'X'
>>> t[3][1] = 'Y'
>>> t[3][2] = 'Z'
>>> t
('a', 'b', 'c', ['X', 'Y', 'Z'])
从表面上看,元组的元素确实是改变了,但其实就变的不是元组的元素,而是列表的元素。下面通过一个元组在内存中的指向图来理解:
](https://imgtu.com/i/a9dFy9)
tuple
一开始指向的list
并没有改变,还是原来的list
。所谓的不变是说元素的指向不变,比如指向a
,就不可以指向b
,指向list
就不可以指向其他对象,但list
本身是可以改变的。
>>> t = ('a','b','c')
>>> id(t)
140665961886488
>>> t = (1,2,3)
>>> id(t)
140665961888144
上面的例子可以很好的证明元素不能改变。虽然t
被重新赋值,但我们知道,元组元素是不能改变的,因此我们通过id()
方法查看前后两个内存地址,发现是不一样的,很明显,t
是绑定(指向)到了新的对象,而不是修改原来的对象。
元组的使用场景
最后来讲下元组的使用情景,虽然有列表跟字符串已经能解决挺多问题,但计算机需要解决的问题还是很多且复杂的,而且元组之所以会存在就自然会有其用处:
- 元组比列表操作速度快。如果定义了一个值,并且唯一要用它做的是不断遍历它,那么请使用元组代替列表。
- 如果对不需要修改的数据进行"写保护",即该数据是常量,那么此时也要使用元组。如果必须要改变这些值,则可以转换为列表修改。
- 元组可以在字典中被用作
Key
,但是列表不可以。因为字典的Key
必须是不可变的。元组本身就是不可变的,而列表是可变的。
改的数据进行"写保护",即该数据是常量,那么此时也要使用元组。如果必须要改变这些值,则可以转换为列表修改。
- 元组可以在字典中被用作
Key
,但是列表不可以。因为字典的Key
必须是不可变的。元组本身就是不可变的,而列表是可变的。