列表是可以修改的,列表非常適合用于存儲(chǔ)程序運(yùn)行期間可能變化的數(shù)據(jù)集贺奠。但是有時(shí)候也需要?jiǎng)?chuàng)建一個(gè)不可修改的元素东涡,元組可以滿足這種需求。Python將不能修改的值稱為不可變的棚潦,而不可變的列表被稱為元組(tuple)令漂。也就是說(shuō),元組是屬于列表的一種丸边,所以元組具備列表的一些特性叠必,比如可以使用索引來(lái)訪問(wèn)元素,也具備列表的方法sort()方法妹窖,只是其元素的值不可變纬朝,因?yàn)橹挡豢勺儯簿蜎](méi)有列表的append()骄呼、insert()這樣的方法共苛。
不可變的元組有什么意義?因?yàn)樵M不可變蜓萄,所以代碼更安全隅茎。如果可能,能用元組代替列表就盡量用元組嫉沽。
8.1 定義元組
8.1.1 語(yǔ)法
元組的定義非常簡(jiǎn)單辟犀,使用圓括號(hào)來(lái)標(biāo)識(shí)。例如绸硕,定義一個(gè)大小不變的三角形踪蹬,將其三邊長(zhǎng)存儲(chǔ)在一個(gè)元組中:
triangle.py
① triangles = (10,6,8)
② print(triangle[0])
③ print(triangle[1])
④ print(triangle[2])
第①行 定義了一個(gè)元組,然后通過(guò)索引分別打印元素臣咖,使用的語(yǔ)法與訪問(wèn)列表元素的語(yǔ)法是相同的:
10
6
8
元組的元素值是不可變的跃捣,如果更改會(huì)發(fā)生什么呢?例如:
① triangles = (10,6,8)
② triangle[0] = 100
第②行 試圖更改元組的第一個(gè)元素的值夺蛇,導(dǎo)致Python返回類型錯(cuò)誤消息疚漆。試圖修改元組的操作是不允許的,因此Python指出不能給元組的元素賦值:
Traceback (most recent call last):
????File "/Users/cunxi/Desktop/triangles.py", line 3, in
????triangle[0] = 100
TypeError: 'tuple' object does not support item assignment
8.1.2 元組不可變的含義
元組不可變刁赦,不能只按表面上的意思去理解娶聘,元組的不可變,指的是元素的指向永遠(yuǎn)不可變甚脉。
numbers.py
numbers = (5,6,[9,2])
numbers[2,0] = 0
numbers[2,1] = 1
print(numbers)
運(yùn)行上述代碼丸升,結(jié)果會(huì)是什么?
是 (5,6,[9,2]) 牺氨?
還是 (5,6,[0,1]) 狡耻?
執(zhí)行結(jié)果:
(5,6,[0,1])
這個(gè)元組numbers定義的時(shí)候有3個(gè)元素墩剖,分別是5、6夷狰、[9,2]岭皂,[9,2]是一個(gè)列表。不是說(shuō)元組一旦定義后就不可變了嗎沼头?怎么后來(lái)又變了爷绘?
我們先看看定義的時(shí)候元組包含的3個(gè)元素:
當(dāng)我們把列表的元素9和2修改為0和1后,元組變?yōu)椋?/p>
表面上看进倍,元組的元素確實(shí)變了土至,但其實(shí)變的不是元組的元素,而是列表的元素猾昆。元組一開(kāi)始指向的列表并沒(méi)有改成別的列表陶因,所以,元組所謂的“不變”是說(shuō)毡庆,元組的每個(gè)元素,指向永遠(yuǎn)不變烙如。即指向5么抗,就不能改成指向6,指向一個(gè)列表亚铁,就不能改成指向其他對(duì)象蝇刀,但指向的這個(gè)列表本身是可變的!
理解了“指向不變”后徘溢,要?jiǎng)?chuàng)建一個(gè)內(nèi)容也不變的元組怎么做吞琐?那就必須保證元組的每一個(gè)元素本身也不能變。
8.1.3 元組定義的陷阱
元組定義有一個(gè)陷阱然爆,當(dāng)你定義一個(gè)元組時(shí)站粟,在定義的時(shí)候,元組的元素就必須被確定下來(lái)曾雕,下面的例子演示這個(gè)陷阱奴烙,代碼在終端演示:
>>> t = (1,2,3)
>>> t
(1,2,3)
如果要定義一個(gè)空的元組:
>>> t = ( )
>>> t
( )
但是,要定義一個(gè)只有1個(gè)元素的元組剖张,這么定義是錯(cuò)誤的:
>>> t = (1)
>>> t
(1)
上述定義的不是元組切诀,而是1這個(gè)數(shù)!因?yàn)?)既可以表示元組搔弄,也可以表示數(shù)學(xué)公式中的小括號(hào)幅虑,這就產(chǎn)生了歧義,Python規(guī)定顾犹,在這種情況下倒庵,按小括號(hào)進(jìn)行計(jì)算褒墨,計(jì)算結(jié)果自然是1。
所以哄芜,只有1個(gè)元素的元組定義時(shí)必須加一個(gè)逗號(hào)貌亭,來(lái)消除歧義:
>>> t = (1,)
>>> t
(1,)
Python在顯示只有1個(gè)元素的元組時(shí),也會(huì)加一個(gè)逗號(hào)认臊,以免被誤解成數(shù)學(xué)計(jì)算意義上的括號(hào)()圃庭。
8.2 遍歷元組中的所有元素
像列表一樣,同樣可以使用for循環(huán)來(lái)遍歷元組中的元素:
triangles = (10,6,8)
for triangle in triangles:
print(triangle)
就像遍歷列表時(shí)一樣失晴,Python返回元組中的所有的元素:
10
6
8
8.3 修改元組變量
雖然不能修改元組的元素值剧腻,但可以給存儲(chǔ)元組的變量賦值。因此涂屁,如果要修改前面的三角形的邊長(zhǎng)书在,可以重新定義整個(gè)元組:
# -*- coding:utf-8 -*-
triangles = (10,6,8)
print("原始尺寸的三角形:")
for triangle in triangles:
print(triangle)
triangles = (3,4,5)
print(" 修改尺寸后的三角形:")
for triangle in triangles:
print(triangle)
先定義了一個(gè)元組,并將其存儲(chǔ)的邊長(zhǎng)打印了出來(lái)拆又;然后儒旬,將一個(gè)新的元組存儲(chǔ)到變量triangles 中,并打印新的邊長(zhǎng)帖族。這次栈源,Python沒(méi)有報(bào)錯(cuò),因?yàn)榻o元組變量賦值是合法的:
原始尺寸的三角形:
10
6
8
修改尺寸后的三角形:
3
4
5
元組是更簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)竖般,如果在程序運(yùn)行期間需要存儲(chǔ)一組不變的值甚垦,可以使用元組。
但是涣雕,如果每次要改變邊長(zhǎng)時(shí)艰亮,都要重新定義一個(gè)新的邊長(zhǎng)元組并賦值,是比較麻煩的挣郭,那么迄埃,如何利用 前面講到的?8.1.2 元素不可變的含義?來(lái)重新改寫(xiě)上述代碼呢?請(qǐng)先思考一下兑障,有助于理解元素不可變的含義调俘,我這里也給出參考實(shí)例。
實(shí)例:
# -*- coding:utf-8 -*-
# 定義三角形函數(shù)
def triangles(a,b,c):
triangle = (a,b,c)
print(triangle)
triangles(10,6,8)
triangles(5,6,4)
執(zhí)行結(jié)果:
(10, 6, 8)
(5, 6, 4)
雖然 函數(shù)內(nèi)部triangle 是一個(gè)元組旺垒,但其a,b,c的值卻可以被改變彩库。隨著編程的深入,會(huì)越來(lái)越多的去了解并掌握一些更深層的東西先蒋,比如變量存儲(chǔ)的方式骇钦,變量是怎么存儲(chǔ)的呢?它一定有一個(gè)存儲(chǔ)地址吧竞漾,類似于每一戶人家都有門(mén)牌號(hào)一樣∶写睿現(xiàn)在不了解沒(méi)關(guān)系窥翩,以后再說(shuō)。
8.4 實(shí)例練習(xí)
實(shí)例1:
① 有一家餐廳鳞仙,只提供4種套餐寇蚊,請(qǐng)將其存儲(chǔ)在一個(gè)元組中。
② 使用for循環(huán)棍好,將這四種套餐都打印出來(lái)
③ 嘗試修改其中的一個(gè)元素仗岸,驗(yàn)證是否可以修改成功
④ 使用len()方法計(jì)算元組的長(zhǎng)度,是否為4
實(shí)例2:
元組具備列表的一些特性借笙,比如扒怖,可以使用min()、max()方法业稼,可以使用負(fù)數(shù)訪問(wèn)倒數(shù)第幾個(gè)元素盗痒,使用切片截取元組的部分元素,請(qǐng)自行嘗試低散。
歡迎關(guān)注公眾號(hào):Python公開(kāi)課俯邓,更多實(shí)例等你來(lái)練習(xí)~