5.3 元组 (tuple) 和序列

我们看见了列表和字符串有很多共同的属性,比如说索引和 slice 操作。一共有两个 序列 数据结构的例子 (见 Sequence Types — list, tuple, range)。因为 Python 是一个不断演变的语言,其他的序列数据结构也可以加进来。另一个序列的数据结构就是:元组 (tuple)

一个元组包含了由逗号分隔开的一些值,举个例子:

  1. >>> t = 12345, 54321, 'hello!'
  2. >>> t[0]
  3. 12345
  4. >>> t
  5. (12345, 54321, 'hello!')
  6. >>> # 元组可以嵌套:
  7. ... u = t, (1, 2, 3, 4, 5)
  8. >>> u
  9. ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
  10. >>> # 元组是不可变的:
  11. ... t[0] = 88888
  12. Traceback (most recent call last):
  13. File "<stdin>", line 1, in <module>
  14. TypeError: 'tuple' object does not support item assignment
  15. >>> # 但是它们可以包含可变对象:
  16. ... v = ([1, 2, 3], [3, 2, 1])
  17. >>> v
  18. ([1, 2, 3], [3, 2, 1])

正如你所看见的那样,输出的元组总是包含在一对圆括号中,所以嵌套的元组可以被正确地解释出来。在输入元组的时候,圆括号可有可无,尽管无论如何圆括号在多数情况下是必需的 (如果元组是一个更大的表达式的一部分)。我们不能给元组中单个元素赋值,但是我们可以创建包含可变对象的元组,比如说包含了列表。

尽管元素看起来和列表很相似,但是它们常常用在不同的场景下用于不同的目的。元组是 不可变对象,而且通常包含了一个有不同种类的元素序列,这些元素通过 解包 (稍后在这一章节后面介绍)或通过 索引 (甚至通过 命名元组 下的属性)来获取。列表是 可变对象,并且它们的元素通常是同种类型的,而且通过遍历这个列表来获取。

有一个特殊的问题,当元组包含 0 个或者 1 个元素的时候的结构:语法为了调整这些情况有一些额外的怪异特性。空的元组由一对空的圆括号组成。只有一个元素的元组由一个值后面跟上一个逗号构成 (把一个单独的值包裹在一对圆括号中是不够充足的)。这样很丑,但是很有效。举个例子:

  1. >>> empty = ()
  2. >>> singleton = 'hello', # <-- 注意跟在后面的逗号
  3. >>> len(empty)
  4. 0
  5. >>> len(singleton)
  6. 1
  7. >>> singleton
  8. ('hello',)

t = 12345, 54321, 'hello!' 这个语句是一个 元组打包 的例子:1234554321hello! 这几个值被打包在一个元组内。倒过来写也可以:

  1. >>> x, y, z = t

这个恰如其分的被称作 序列解包,可以为右侧的任何序列起作用。序列解包要求等号左边的变量需要和序列中的元素一样多。注意,多重赋值真的仅仅是元组打包和序列解包的一种结合。