2.8. 元組

元組(tuple)是一個不可變、有序的值序列。一旦建立,裡面的項目就不能再被新增、移除或更改。

2.8.1. 建立元組

使用小括號(或僅用逗號)來建立元組:

empty   = ()
point   = (3, 4)
triple  = 1, 2, 3                # parentheses are optional
mixed   = (1, "two", 3.14)
nested  = ((1, 2), (3, 4))

2.8.1.1. 單一元素的陷阱

包在值外面的小括號就只是小括號;真正構成元組的是逗號。單一元素的元組需要一個尾隨的逗號:

>>> (1)
1                                # just an int in parens
>>> (1,)
(1,)                             # a one-element tuple
>>> type((1)), type((1,))
(<class 'int'>, <class 'tuple'>)

2.8.2. 長度、索引與切片

與串列和字串相同—— len()、索引、切片、in,以及 +* 的運作方式都相同:

>>> point = (3, 4, 5)
>>> len(point)
3
>>> point[0]
3
>>> point[1:]
(4, 5)
>>> 4 in point
True
>>> (1, 2) + (3, 4)
(1, 2, 3, 4)

2.8.3. 不可變性

元組沒有 appendpopsort 或任何其他就地修改的方法。索引賦值會引發 TypeError

>>> point = (3, 4)
>>> point[0] = 99
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object doesn't support item assignment

若要「修改」一個元組,請以更改後的值建立一個新的元組。

2.8.4. 解包

元組的主要超能力是解包(unpacking):在單一陳述句中將每個項目指派給各自獨立的變數。

一個三元素元組 (1, 2, 3) 解包成三個 具名變數 x、y、z。

解包會在單一賦值中將元組的每個元素繫結到一個具名變數。

>>> point = (3, 4)
>>> x, y = point
>>> x
3
>>> y
4

右側可以是任何可迭代物件——串列、字串,或函式的回傳值:

>>> a, b, c = "abc"
>>> a, b, c
('a', 'b', 'c')

開頭的 * 會將解包中「其餘」的部分收集成一個串列:

>>> first, *rest = [10, 20, 30, 40]
>>> first
10
>>> rest
[20, 30, 40]

2.8.5. 多個回傳值

函式可以回傳一個元組以一次傳遞多個值;呼叫端在接收時將它們解包:

def size_of(rect):
    return (rect[2] - rect[0], rect[3] - rect[1])

width, height = size_of((10, 20, 110, 140))
# width = 100, height = 120

return 上的小括號是可選的——光禿禿的 return a, b 也是一個元組。

2.8.6. 元組與串列的比較

關於該選用哪一種的實用指南:

  • 元組適用於形狀固定、通常為異質的資料:(x, y) 座標點、(r, g, b) 色彩、多個回傳值,以及為日後使用而打包的函式引數。

  • 串列適用於長度可變、通常為同質的資料:一串測量值、一個待處理項目的佇列,以及任何你預期會去附加內容的東西。

元組也是可雜湊的(只要其中每個元素都是可雜湊的),因此它們可以用作 dict 中的鍵。