**值得注意:**从形式上,元组的所有元素放在一对圆括号中,元素之间使用逗号分隔,如果元组中只有一个元素则必须在最后增加一个逗号。
>>> x = (1, 2, 3) #直接把元组赋值给一个变量
>>> type(x) #使用type()函数查看变量类型
<class 'tuple'>
>>> x[0] #元组支持使用下标访问特定位置的元素
1
>>> x[-1] #最后一个元素,元组也支持双向索引
3
>>> x[1] = 4 #元组是不可变的
TypeError: 'tuple' object does not support item assignment
>>> x = (3) #这和x = 3是一样的
>>> x
3
>>> x = (3,) #如果元组中只有一个元素,必须在后面多写一个逗号
>>> x
(3,)
>>> x = () #空元组
>>> x = tuple() #空元组
>>> tuple(range(5)) #将其他迭代对象转换为元组
(0, 1, 2, 3, 4)
很多内置函数的返回值也是包含了若干元组的可迭代对象,例如enumerate()、zip()等等。
>>> list(enumerate(range(5)))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
>>> list(zip(range(3), 'abcdefg'))
[(0, 'a'), (1, 'b'), (2, 'c')]
列表和元组都属于有序序列,都支持使用双向索引访问其中的元素,以及使用count()
方法统计指定元素的出现次数和index()方法获取指定元素的索引,len()、map()、filter()
等大量内置函数和+、in等运算符也都可以作用于列表和元组。
元组属于不可变(immutable)序列,不可以直接修改元组中元素的值,也无法为元组增加或删除元素。
元组没有提供append()、extend()和insert()
等方法,无法向元组中添加元素;同样,元组也没有remove()
和pop()
方法,也不支持对元组元素进行del
操作,不能从元组中删除元素,而只能使用del命令删除整个元组。
元组也支持切片操作,但是只能通过切片来访问元组中的元素,而不允许使用切片来修改元组中元素的值,也不支持使用切片操作来为元组增加或删除元素。
Python的内部实现对元组做了大量优化,访问速度比列表更快。如果定义了一系列常量值,主要用途仅是对它们进行遍历或其他类似用途,而不需要对其元素进行任何修改,那么一般建议使用元组而不用列表。
元组在内部实现上不允许修改其元素值,从而使得代码更加安全,例如调用函数时使用元组传递参数可以防止在函数中修改元组,而使用列表则很难保证这一点。
元组可用作字典的键,也可以作为集合的元素。而列表则永远都不能当作字典键使用,也不能作为集合中的元素。
生成器推导式(generator expression)的用法与列表推导式非常相似,在形式上生成器推导式使用圆括号(parentheses)作为定界符,而不是列表推导式所使用的方括号(square brackets)。
与列表推导式最大的不同是,生成器推导式的结果是一个生成器对象。生成器对象类似于迭代器对象,具有惰性求值的特点,只在需要时生成新元素,比列表推导式具有更高的效率,空间占用非常少,尤其适合大数据处理的场合。
使用生成器对象的元素时,可以根据需要将其转化为列表或元组,也可以使用生成器对象的__next__()
方法或者内置函数next()
进行遍历,或者直接使用for循环来遍历其中的元素。但是不管用哪种方法访问其元素,只能从前往后正向访问每个元素,没有任何方法可以再次访问已访问过的元素,也不支持使用下标访问其中的元素。当所有元素访问结束以后,如果需要重新访问其中的元素,必须重新创建该生成器对象,enumerate、filter、map、zip
等其他迭代器对象也具有同样的特点。
使用生成器对象__next__()方法或内置函数next()进行遍历
>>> g = ((i+2)**2 for i in range(10)) #创建生成器对象
>>> g
<generator object <genexpr> at 0x0000000003095200>
>>> tuple(g) #将生成器对象转换为元组
(4, 9, 16, 25, 36, 49, 64, 81, 100, 121)
>>> list(g) #生成器对象已遍历结束,没有元素了
[]
>>> g = ((i+2)**2 for i in range(10)) #重新创建生成器对象
>>> g.__next__() #使用生成器对象的__next__()方法获取元素
4
>>> g.__next__() #获取下一个元素
9
>>> next(g) #使用函数next()获取生成器对象中的元素
使用for循环直接迭代生成器对象中的元素
>>> g = ((i+2)**2 for i in range(10))
>>> for item in g: #使用循环直接遍历生成器对象中的元素
print(item, end=' ')
4 9 16 25 36 49 64 81 100 121
访问过的元素不再存在
>>> x = filter(None, range(20)) #filter对象也具有类似的特点
>>> 5 in x
True
>>> 2 in x #不可再次访问已访问过的元素
False
>>> x = map(str, range(20)) #map对象也具有类似的特点
>>> '0' in x
True
>>> '0' in x #不可再次访问已访问过的元素
False