深挖 Python 元組 pt.2
哈嘍大家好,我是咸魚
在《深挖 Python 元組 pt.1》中我們了解 Python 元組的一些概念(索引和切片等),以及如何創(chuàng)建元組,最重要的是我們還介紹了元組的不可變特性
那么今天我們來繼續(xù)深挖 Python 元組
打包&解包
在 python 中,元組可以被打包(packing )和解包(unpacking )
例如,point = x, y, z 將會(huì)把 x, y 和 z 的值打包到 point 中,于是創(chuàng)建了一個(gè)新元組
圖片
我們還可以執(zhí)行反向操作(解包),將元組 point 的值解包為適當(dāng)數(shù)量的變量
圖片
可以看到,x, y, z = point 神奇地將point的內(nèi)容解壓縮為三個(gè)變量。注意,值按順序轉(zhuǎn)到變量。(第一個(gè)值歸第一個(gè)變量,第二個(gè)值歸第二個(gè)變量,依此類推)
Python 3.5 擴(kuò)展了元組解包語法,以處理各種可迭代對(duì)象
所以不單單元組可以解包,可迭代對(duì)象也可以解包
在常規(guī)解包中,變量的數(shù)量必須與要解包的值的數(shù)量相匹配。否則會(huì)報(bào)錯(cuò)
圖片
解包最常見的用例就是利用解包在變量之間交換值
沒有解包的話使用常規(guī)賦值在兩個(gè)變量之間交換值,必須使用臨時(shí)變量
圖片
通過解包來交換變量值
圖片
解包還有一個(gè)用處是并行分配,比如說下面的操作:我們?cè)谶M(jìn)行賦值時(shí)需要知道對(duì)應(yīng)的索引
圖片
如果通過解包來實(shí)現(xiàn),則無需使用索引。這樣能使代碼更易閱讀和理解,且不易出錯(cuò)
圖片
Python 還有一個(gè)打包和解包運(yùn)算符 ( * ),我們可以使用它讓解包(打包)操作更加靈活
例如當(dāng)左邊的變量數(shù)和右邊元組的元素?cái)?shù)量不匹配時(shí),可以使用 * 使得單個(gè)變量接收多個(gè)值
圖片
關(guān)于這個(gè)操作符的更多用法,可以看我之前的文章:《python 星號(hào) * 還能這么用》
函數(shù)返回元組
在某些情況下,需要從函數(shù)返回多個(gè)值。所以可以構(gòu)建一個(gè)帶有逗號(hào)分隔的一系列參數(shù)的 return 語句,這樣返回的是一個(gè)元組
我們還可以使函數(shù)返回值是列表,這樣需要我們顯式地使用方括號(hào)來構(gòu)建列表
內(nèi)置 divmod() 函數(shù)是返回多個(gè)值的函數(shù)的一個(gè)很好的例子。該函數(shù)接受兩個(gè)數(shù)字,并在執(zhí)行整數(shù)除法時(shí)返回一個(gè)包含商和余數(shù)的元組:
圖片
又或者我打算寫一個(gè)函數(shù),這個(gè)函數(shù)返回一組數(shù)的最大值和最小值
圖片
可以看到函數(shù)的返回值有兩個(gè):最大值、最小值。當(dāng)用逗號(hào)分隔一系列值時(shí),將創(chuàng)建一個(gè)元組。因此,此函數(shù)返回一個(gè) tuple 對(duì)象
深拷貝&淺拷貝
當(dāng)需要轉(zhuǎn)換數(shù)據(jù)時(shí),通常需要復(fù)制對(duì)象,同時(shí)保持原始數(shù)據(jù)不變。在處理可變數(shù)據(jù)類型(如列表和字典)時(shí),副本非常有用
副本可以在不影響原數(shù)據(jù)的情況下對(duì)數(shù)據(jù)進(jìn)行更改
- 直接賦值
我們先來看一個(gè)例子
圖片
可以看到,student_info、 student_profile 是對(duì)同一元組對(duì)象的引用。所以, student_profile 是 的 student_info 別名而不是副本
- 淺拷貝
copy 模塊中的 copy() 函數(shù)生成等效結(jié)果
圖片
可以看到,兩個(gè)變量student_info、 student_profile 都包含對(duì)同一元組對(duì)象和相同元素的引用
上面的元組里面包含了一個(gè)列表元素,我們知道列表是可變的,我們來試著更改一下
圖片
可以看到,student_profile 更改會(huì)影響 student_info 中的原始數(shù)據(jù)
- 深拷貝
下面的例子中, student_info 通過 deepcopy() 函數(shù)制作了student_profile
圖片
可以看到,兩個(gè)變量student_info、 student_profile 指向的元組對(duì)象不是同一個(gè)
如果我們對(duì)里面的列表元素進(jìn)行更改
圖片
可以看到,對(duì)student_profile 的修改不會(huì)影響 student_info 中的數(shù)據(jù)
總結(jié)一下:
- 元組的淺拷貝不會(huì)創(chuàng)建一個(gè)新的對(duì)象(副本)。
- 元組的深拷貝創(chuàng)建一個(gè)新的元組對(duì)象
- 對(duì)于元組內(nèi)的不可變?cè)?,它們?nèi)匀粫?huì)共享相同的內(nèi)存地址
- 對(duì)于元組內(nèi)的可變?cè)?,則是創(chuàng)建了一個(gè)新的對(duì)象,不共享內(nèi)存地址
其他操作
- 元組拼接和重復(fù)
在 Python 中連接兩個(gè)元組,可以使用加號(hào)運(yùn)算符 ( + )
圖片
需要注意的是,+ 左右兩邊必須都是元組,即只能將元組跟元組拼接。如果元組跟列表或其他對(duì)象拼接的話,會(huì)報(bào)錯(cuò)
圖片
元組使用重復(fù)運(yùn)算符 ( * )將元素克隆多次
圖片
- 元組反轉(zhuǎn)和排序
內(nèi)置 reversed() 函數(shù)將序列作為參數(shù),并返回一個(gè)迭代器,該迭代器以相反的順序從輸入序列生成值。
圖片
使用元組作為參數(shù)進(jìn)行調(diào)用 reversed() 時(shí),將獲得一個(gè)迭代器對(duì)象,該對(duì)象以相反的順序生成項(xiàng)
如果要對(duì)元組進(jìn)行排序,可以使用內(nèi)置 sorted() 函數(shù),該函數(shù)將值的可迭代對(duì)象作為參數(shù)并以列表形式返回排序后的值
圖片
如果元組里面的元素?cái)?shù)據(jù)類型不一致(異構(gòu)數(shù)據(jù)),則無法排序