python的元组是有序且不可被修改的数据集合,使用小括号() 进行定义,元组内的元素之间使用逗号分隔。从形式上观察,除了用小括号()代替了中括号[],元组几乎与列表一样,但元组有自己独特的特性:元组一旦被创建就无法被修改,新增,删除,修改这些操作都无法在元组上进行。
使用小括号,可以创建一个空的元组
t = ()
print(type(t)) # <class 'tuple'>
创建只有一个元素的元组
t = (5, )
print(type(t)) # <class 'tuple'>
即便元组里只有一个元素,也要写入一个逗号,因为小括号()既可以表示为元组的定义形式,也可以作为括号表示算数运算时的优先级,如果没有逗号,(5) 将被解析成int类型的5,在下面的表达式里,()不在被认为是元组的定义形式。
>>> 5 == (5)
True
创建拥有多个元素的元组
t = ('python', 'java', 'php')
print(t) # ('python', 'java', 'php')
使用内置函数tuple创建元组
t1 = tuple(['python', 'java', 'php'])
print(t1) # ('python', 'java', 'php')
t2 = tuple('python')
print(t2) # ('p', 'y', 't', 'h', 'o', 'n')
获取元组里的值,方法与从列表里获取值一样,必须提供索引,通过[]索引访问的方式获得索引对应的值。
t = tuple(['python', 'java', 'php'])
print(t[0]) # python
通过for循环同样可以对元组进行遍历
t = tuple(['python', 'java', 'php'])
for item in t:
print(item)
元组同样支持切片操作,这方面与列表完全一致
t = tuple(['python', 'java', 'php'])
print(t[1:]) # ('java', 'php')
只要不修改元组,对列表的一切操作都可以移植到元组身上。
元组是不可变对象,但有人却提出的反例
t = ([1, 2, 3], ['python'])
t[0][0] = 3
print(t)
元组t里有两个元组,两个元组都是列表,程序执行的结果是
([3, 2, 3], ['python'])
看起来,元组似乎成功被修改了,然而这并不是事实,元组没有被修改,被修改的是列表里的元素,准确的说是t[0]被修改了,而t没有被修改。
当我们强调元组是不可变对象时,是指无法通过索引修改元组里的元素,类似下面的代码是无法被执行的
t = ([1, 2, 3], ['python'])
t[0] = '修改'
程序会报错
TypeError: 'tuple' object does not support item assignment
t[0] 是列表,我们不能将元组的第一个元素修改为其他对象,但t[0]作为列表本身是可以被修改的,但修改以后,t[0]还是原来的那个列表,只是列表里的内容发生了变化,元组t没有发生变化,仍然只有两个元素,通过内置函数id输出t[0]的内存地址能让你更清楚的认识到元组没有被修改。
t = ([1, 2, 3], ['python'])
print(id(t[0])) # 2161425011080
t[0][0] = 3
print(id(t[0])) # 2161425011080
修改前后,t[0]的内存地址不变,从元组的视角来看,它内部存储的第一个元素没有发生改变。
很多人认为元组就是一个不可变的列表,虽然很形象,但并不准确。python在元组内部做了很多优化,既节省了内存又提高了性能,元组有自己特殊的使用场景,这是列表无法替代的。
def func(x, y):
return x, y, x+y
res = func(2, 3)
print(res)
当函数有多个返回值时,最终以元组的形式返回,程序输出结果为
(2, 3, 5)
当函数返回多个结果时,以列表的形式返回,难道不也是可行的么?从程序设计的角度看,函数返回多个结果时,以元组形式返回好于以列表形式返回,原因在于列表是可变对象,这意味着函数的返回结果是可修改的,那么函数在使用时就容易出现修改函数返回值的情况。
某些情况下,我们不希望函数的返回值被他人修改,元组恰好满足了我们的要求,如果函数本意就是返回一个列表,那么在renturn时,就应该直接返回列表,而不是返回多个结果。
def func(*args):
print(args, type(args))
func(3, 4, 5)
定义一个支持可变参数的函数时,args的类型是元组,在函数内可以从args中依次取出传入的参数,那么同样的问题,为什么不是列表呢?还是从程序设计的角度出发,如果args被设计成列表,由于列表可以被修改,保不齐某个程序员在实现函数的时候修改了args,传入的参数被修改了,或是增加,或是减少,这样就会引发不可预知的错误。
但现在,python将其设计成元组,元组无法修改,你在函数内部无法修改传入的参数,这就保证了函数入参的安全性。
想要成为字典的key,或是存储到集合中,必须满足可hash这个条件,所有的可变对象,诸如列表,集合,字典都不能做key,但元组可以,在一些特定情境下,用元组做key,非常实用,比如下面这个练习题目
题目要求:已知有两个列表
lst1 = [3, 5, 6, 1, 2, 4, 7]
lst2 = [6, 5, 4, 7, 3, 8]
从两个列表里各取出一个数,他们的和如果为10,则记录下来,请写程序计算,这种组合一共有几种,分别是什么,要求组合不能重复。
从lst1中取3, lst2中取7,这对组合满足要求,从lst1中取7,lst2中取3,也满足要求,但是这个组合已经存在了,因此不算。
使用嵌套循环,就可以轻易的完成这个题目,但是这中间过程要去除掉重复的组合,正好可以利用元组,算法实现如下
lst1 = [3, 5, 6, 1, 2, 4, 7]
lst2 = [6, 5, 4, 7, 3, 8]
res_set = set()
for i in lst1:
for j in lst2:
if i + j == 10:
if i > j:
res_set.add((j, i))
else:
res_set.add((i, j))
print(res_set)
程序输出结果
{(3, 7), (4, 6), (5, 5), (2, 8)}
去重的过程恰好利用了元组,将组合以元组的形式存储到集合中,利用集合的不重复性来达到去重的目的,元组里第一个元素是组合中较小的那个数
QQ交流群: 211426309