元组与列表
您可能已经注意到,元组与列表非常相似。实际上,可以把它看作不可变的列表,这意味着一旦创建了元组,您就不能删除或更改其中项目的值,也不能添加新值。请看下面的示例:
numbers_tuple = (1,2,3,4,5)
numbers_list = [1,2,3,4,5]
# Append a number to the tuple
numbers_tuple.append(6)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-26-e47776d745ce> in <module>()
3
4 # Append a number to the tuple
----> 5 numbers_tuple.append(6)
AttributeError: 'tuple' object has no attribute 'append'
这会抛出错误,因为您不能从元组中删除或向其添加元素,而列表可以。
# Append numbers to the list
numbers_list.append(6)
numbers_list.append(7)
numbers_list.append(8)
# Remove a number from the list
numbers_list.remove(7)
print(numbers_list)
[1, 2, 3, 4, 5, 6, 8]
但如果元组是不可变的,为什么还要用它呢?
不仅因为它们为数据值提供“只读”访问,而且它们也比列表更快。请看以下代码片段:
import timeit
timeit.timeit('x=(1,2,3,4,5,6,7,8,9)', number=100000)
0.0018976779974764213
timeit.timeit('x=[1,2,3,4,5,6,7,8,9]', number=100000)
0.019868606992531568
对于元组来说,不可变究竟意味着什么?
根据 Python 官方文档,不可变对象是“具有固定值的对象”,但“值”这个词相对含糊,对元组更准确的术语是“id”。“id”是对象在内存中的位置标识。
让我们更深入地看一下:
# Tuple 'n_tuple' with a list as one of its item.
n_tuple = (1, 1, [3,4])
#Items with same value have the same id.
id(n_tuple[0]) == id(n_tuple[1])
True
#Items with different value have different id.
id(n_tuple[0]) == id(n_tuple[2])
False
id(n_tuple[0])
4297148528
id(n_tuple[2])
4359711048
n_tuple.append(5)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-40-3cd258e024ff> in <module>()
----> 1 n_tuple.append(5)
AttributeError: 'tuple' object has no attribute 'append'
我们无法向元组追加元素,因此如上会报错。这也是元组被称为不可变的原因。但您始终可以这样做:
n_tuple[2].append(5)
n_tuple
(1, 1, [3, 4, 5])
这样实际上改变了原始元组。那么为什么元组仍被称为不可变呢?
这是因为,即使您向其中的列表追加了 5,该列表在元组中的 id 仍保持不变。
id(n_tuple[2])
4359711048
总结一下目前为止您学到的内容:
某些元组(仅包含不可变对象:字符串等)是不可变的,而另一些元组(包含一个或多个可变对象:列表等)则是可变的。不过,这往往是 Python 开发者之间的一个可讨论话题,完全理解还需要更多背景知识。关于此话题的更深入文章请见这里。目前,我们不妨将元组一般视为不可变。
- 由于不可变特性,您不能向元组添加元素。元组没有
append()或extend()方法, - 同样地,您也不能从元组中移除元素。元组没有
remove()或pop()方法, - 您可以在元组中查找元素,因为这不会改变元组,
- 您还可以使用
in运算符检查某元素是否存在于元组中。
因此,如果您要定义一组常量值,并且只是遍历它,请使用元组而不是列表。它比使用列表更快,也更安全,因为元组中的数据是“写保护”的。
如果您想进一步了解 Python 列表,请务必查看这篇教程!
常见元组操作
Python 提供了多种处理元组的方式。下面通过示例看看一些重要操作。
元组切片
元组中第一个值的索引为 0。与 Python 列表类似,您可以结合使用索引值与方括号 [] 来访问元组中的元素:
numbers = (0,1,2,3,4,5)
numbers[0]
0
您也可以在元组中使用负索引:
numbers[-1]
5
索引用于获取单个元素,而切片则允许您获取子集。当您输入想要提取的范围时,这称为范围切片。范围切片的一般格式为:
[Start index (included):Stop index (excluded):Increment]
其中 Increment 为可选参数,默认增量为 1。
# Item at index 4 is excluded
numbers[1:4]
(1, 2, 3)
# This provides all the items in the tuple
numbers[:]
(0, 1, 2, 3, 4, 5)
# Increment = 2
numbers[::2]
(0, 2, 4)
提示:您也可以使用负增量值来反转元组。
numbers[::-1]
(5, 4, 3, 2, 1, 0)
元组相加
您可以将多个元组合并形成新元组。加法操作对元组而言就是连接(拼接)。
x = (1,2,3,4)
y = (5,6,7,8)
# Combining two tuples to form a new tuple
z = x + y
print(z)
(1, 2, 3, 4, 5, 6, 7, 8)
y = [5,6,7,8]
z = x + y
print(z)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-55-d352c6414a4c> in <module>()
1 y = [5,6,7,8]
----> 2 z = x + y
3 print(z)
TypeError: can only concatenate tuple (not "list") to tuple
只能将相同数据类型相加或合并。因此,将元组与列表合并会报错。
元组乘法
乘法操作会对元组进行重复。
x = (1,2,3,4)
z = x*2
print(z)
(1, 2, 3, 4, 1, 2, 3, 4)
元组函数
与 Python 列表不同,元组由于其不可变性,没有 append()、remove()、extend()、insert() 和 pop() 等方法。不过,还有许多其他内置函数可用于处理元组:
count() 和 len()
count() 返回某个项目在元组中出现的次数。
a = [1,2,3,4,5,5]
a.count(5)
2
使用 len() 函数,您可以返回元组的长度:
a = (1,2,3,4,5)
print(len(a))
5
any()
您可以使用 any() 判断元组中是否存在任一元素为可迭代对象。如果是,则返回 True,否则返回 False。
a = (1,)
print(any(a))
True
请注意上面元组 a 的声明中带有 ,。如果在初始化只有一个元素的元组时不加逗号,Python 会认为您只是多写了一对括号(这无伤大雅),但数据类型就不是元组了。因此,声明单元素元组时请记得添加逗号。
回到 any() 函数:在布尔上下文中,元素的具体值并不重要。空元组为 false,至少包含一个元素的元组为 true。
b = ()
print(any(b))
False
当您在程序中某处调用一个元组,并希望确保该元组已被填充时,此函数会很有用。
tuple()
使用 tuple() 将其他数据类型转换为元组。例如,在下面的代码片段中,您将一个 Python 列表转换为元组。
a_list = [1,2,3,4,5]
b_tuple = tuple(a_list)
print(type(b_tuple))
<class 'tuple'>
min() 和 max()
max() 返回元组中的最大元素,而 min() 则返回最小元素。请看以下示例:
print(max(a))
print(min(a))
5
A
这也适用于包含字符串数据类型的元组。
# The string 'Apple' is automatically converted into a sequence of characters.
a = ('Apple')
print(max(a))
p
sum()
使用该函数可以返回元组中所有项目的总和。它只能用于数值类型。
sum(a)
28
sorted()
要返回按排序顺序排列元素的结果,请使用 sorted(),如下例所示:
a = (6,7,4,2,1,5,3)
sorted(a)
[1, 2, 3, 4, 5, 6, 7]
需要注意的是,返回类型是列表而不是元组。原始元组 a 中的顺序不会改变,a 的数据类型仍然是元组。
加餐:一次赋多个值
元组的一个妙用是可以用它一次性为多个变量赋值。请看:
a = (1,2,3)
(one,two,three) = a
print(one)
1
a 是一个包含三个元素的元组,而 (one,two,three) 是包含三个变量的元组。将 (one,two,three) 赋值为元组 a 会按顺序把 a 的各个值分别赋给变量 one、two 和 three。当您需要将一系列值赋给一个元组中存放的序列时,这个技巧非常实用。
恭喜!
您已读完本次元组教程!在此过程中,您了解了什么是 Python 元组、如何初始化它们、可以用哪些最常见的操作来处理它们,以及有哪些常用方法可以帮助您从这些 Python 数据结构中获取更多洞见。作为加餐,您还学会了如何一次性为元组解包并赋多个值。
与 Python 列表类似,元组是另一种标准数据类型,允许您以序列的形式存储值。它在需要与他人共享数据但不希望对方修改数据的场景中非常有用。对方可以使用这些数据值,但对原始共享数据不会产生任何更改。
在本教程中,您将详细了解 Python 元组:
别忘了查看 DataCamp 的 Data Types for Data Science 课程,您可以在其中巩固并练习列表、字典、集合等数据结构的知识!或者,也可以看看这篇 Python 数据结构教程,进一步了解 Python 所使用的不同数据结构。
Python 元组
如上所述,您可以使用这种 Python 数据结构来存储一个不可变(或不可更改)且有序的项目序列。
元组使用
()圆括号初始化,而列表使用[]方括号。这意味着要创建一个元组,您只需执行以下操作:请记住,
type()是一个内置函数,可用于检查传入参数的数据类型。元组既可以保存同质的值,也可以保存异质的值。但请注意,一旦您声明了这些值,就不能再更改它们:
您会看到上述错误消息,是因为您不能更改元组内的值。
以下是创建元组的另一种方式: