本文沒有太多學習性的東西!!! 更多的是擴展你對Python的認知.
- 這篇帖子主要講講幾個月前看的一本書,《流暢的Python》這本書是由一位奮戰在Python開發一線的大牛寫的,書中有講了多關於Python的神奇特性,對你寫一段地道的Pythonic非常有幫助.
元組不可修改or可修改
結合曾經的學習經驗,你一定會認爲Python的元組是不可修改的序列.就像下面的代碼,你應該已經知道了結果.
(代碼均使用交互式環境執行)
>>> t = (1,2,3,4)
>>> t.append(5)
# >>> AttributeError: 'tuple' object has no attribute 'append'
>>> t += (5)
# >>> TypeError: can only concatenate tuple (not "int") to tuple
從報錯上來看,元組是沒有append()方法的 (這與魔術方法有關,如果你瞭解魔術方法那你也許就能夠明白爲什麼元組不可修改),所以使用append()方法對元組進行修改的思想就先放放吧,但是觀察一下使用 += 對元組進行修改時的報錯卻是一個 TypeError ,所以由此衍生出了一個想法 “能否改變對象 (對象包括修改的元組和添加的對象) 的類型使得可以使用+=的將元組進行修改”.
>>> t = (1,2,3)
>>> t+=(())
# >>>
>>> t
# >>> (1,2,3)
從上面的代碼中可以看到改變類型確實可以完成元組的修改,雖然是沒有意義的,但是重要的是沒有報錯!!!
再次改變想法,如果改變的是元組的類型會怎麼樣,可能到這你不太能夠理解我的意思,但是並沒有什麼大礙,閱讀下面的代碼你一定能夠快速理解.
>>> t = (1,2,3,[4,5])
>>> t[3].append(6)
如果是這樣的一段代碼結果會怎麼樣呢?
>>> t
# >>> (1,2,3,[4,5,6])
答案是元組的列表成功的被append()方法修改了 (還是和魔術方法有關係,因爲列表中有關於append()方法的魔術方法,所以使列表變得可以修改了) ,再回到修改方式,如果使用 **+=**會怎麼樣? 是否和append()方法的結果一樣呢?
>>> t = (1,2,3,[4,5])
>>> t[3] += [6] # 保證類型一致
# >>> t[3] += ([6]) # 兩段代碼結果一樣,看自己可以理解的就行
# !!! 錯誤示範:
# >>> t[3] += (6) # 不同的數據類型不可以進行運算!!!
# Output:
# >>> TypeError: 'tuple' object does not support item assignment
從上面的代碼中可以看到,最後的結果是一段報錯,但是結合之前的append()方法,按理來說元組內的列表應該能夠被正常修改,但是爲什麼結果卻是一個報錯呢? (元組發現了+=是用來修改的所以產生了報錯)
接下來的代碼是在上一段代碼的基礎之上進行輸出的(這也是選擇交互式環境的理由)
>>> t
# >>> (1,2,3,[4,5,6])
雖然在進行修改是產生了報錯,但是最後的輸出結果卻是修改成功的!!! 由上面的代碼可以知道,元組內的可修改序列是可以被修改的!!!這是一個重點,所以在使用元組的時候經歷千萬不要把可修改序列放在其中!!!
總結:
- 不要把可修改序列放在元組中!!!
- 增量賦值不是一個原子操作(所謂的原子操作,取的就是“原子是最小的、不可分割的最小個體”的意義)
Python運行原理可視化(Python Tutor): http://www.pythontutor.com