python中的可變數據類型有列表和元組_Python中列表的 += 和 .extend() 的異同

一道Python題

最近有朋友“考”了我一個Python的題:使用+=和.extend()兩種方法擴展元組中的列表會發生什么。雖然我對Python中的可變數據類型、不可變數據類型的概念都有較深的理解,并且也對list的+、+=、.extend()、.append()做過性能分析,但是+=和.extend()兩者無論在表現(是否為原地址修改)以及性能上都非常近似,所以對兩者的區別還沒有明確的概念。為了解答這個問題,我我們先直接上代碼試驗一下:# 創建一個包含列表的元組:

>>> a_tuple = (1, 2, [])

>>> a_tuple[2] += ['a', 'b'] # (1)

Traceback (most recent call last):

File "", line 1, in

a_tuple[2] += ['a', 'b']

TypeError: 'tuple' object does not support item assignment

>>> a_tuple[2].extend(['a', 'b']) # (2)

>>> a_tuple # (3)

(1, 2, ['a', 'b', 'a', 'b'])(1) 通過+=的方法擴展列表出現“元組不支持元素賦值”的報錯。

(2) 使用.extend()方法。

(3) 有趣的是,列表被擴展了兩次。雖然+=報錯,但是卻成功修改了列表。

Python中的可變數據類型和不可變數據類型

要解釋這個先從Python中的可變數據類型和不可變數據類型談起。可變數據類型可以在不改變內存地址的情況下對其進行修改。而不可變數據類型只能重新賦值綁定變量,這時變量的內存地址已經發生變化,而原地址的數據在沒有被其他變量引用后將被GC(garbage collector)回收:>>> a = 1

>>> id(a) # CPython通過id()查看變量a的內存地址

1942286128

>>> a += 1 # 對變量a進行修改

>>> id(a) # 這時內存地址已經發生變化

1942286160

>>> a_list = [1] # list為可變數據類型

>>> id(a_list)

2170470080648

>>> a_list.append(2)

>>> id(a_list) # 修改后內存地址沒有變化

2170470080648

元組不能修改?

學Python時教材里一般都會說元組不能修改,沒有.append()、.extend()、.insert()這些方法。沒錯,元組是不可變數據類型,確實不能修改。但是元組的元素可以是可變數據類型,而元組中保存的實際是可變數據類型的內存地址。所以通過對可變數據類型的修改,元組最終返回的數據是可以變化的。如果了解C語言中“指針”概念的話就很好懂了。

對于list這種可變數據類型,+=和.extend()有什么異同?

還是接上面那個例子:>>> id(a_list)

2170470080648

>>> a_list += [3]

>>> id(a_list) # 通過+=擴展list,內存地址沒有變化

2170470080648

>>> a_list.extend([4])

>>> id(a_list) # 通過.extend()擴展list,當然內存地址也不會變化

2170470080648

>>> a_list = a_list + [5] # 會這樣寫的真是個人才

>>> id(a_list) # 地址發生了變化

2170470080712

這樣來說+=和.extend()在修改list時都不會修改地址,那為什么題目中通過這兩種方法修改a_tuple中的list會有不同的結果呢?其實Python中兩者的行為確實不同:Python中的.extend()就是在原始內存地址上對list進行了擴展,沒有改變內存地址,也就不會報錯。

+= 在不可變對象中調用.__add__()(和+一致);而在可變對象中調用的是.__iadd__()(原地址修改)。

.__iadd__()實際上已經成功在原地址修改了列表,但是它會對的a_tuple[2]進行重新賦值,而這一步引發了報錯,因為元組的元素不能修改。

怎么避免類似的坑?

我認為Tim Peters的《Zen of Python》(Python之禪)里有一句話很經典:There should be one-- and preferably only one --obvious way to do it.

——應當存在一種,而且更應該只有一種最好的解決方案。

所以我的回答是——你基本上不可能記住所有的特例,最簡單粗暴的方法就是意識到:當你遇到一個可能的坑,意味著這不是最好的解決方案,那就忘了它,然后記住最好的。在這里就是記住擴展列表用.extend(),忘記+=吧!

附:+、+=、.extend()、.append()的性能分析:import time

def cal_time(func):

def wrapper():

t1 = time.time()

func()

t2 = time.time()

print(t2-t1)

return wrapper

@cal_time

def func_a():

a = []

for x in range(100000):

a = a + [x]

@cal_time

def func_b():

a = []

for x in range(100000):

a += [x]

@cal_time

def func_c():

a = []

for x in range(100000):

a.extend([x])

@cal_time

def func_d():

a = []

for x in range(100000):

a.append(x)

func_a()

func_b()

func_c()

func_d()

Python 3.5.1測試結果:24.90237021446228 # a = a + [x]

0.01898360252380371 # a += [x]

0.02698493003845215 # a.extend([x])

0.013987541198730469 # a.append(x)

參考資料

在總結這篇文章的時候發現其實這個問題早已經在官方文檔的FAQ有非常明確的解答了,推薦閱讀:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/260285.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/260285.shtml
英文地址,請注明出處:http://en.pswp.cn/news/260285.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

簡易貪吃蛇小游戲java版_用GUI實現java版貪吃蛇小游戲

本文實例為大家分享了java版貪吃蛇小游戲的具體代碼,供大家參考,具體內容如下項目結構新建一個JFrame窗口,作為程序入口public class GameStart{public static void main(String[] args) {JFrame jFrame new JFrame();jFrame.setBounds(100,100,900,720…

幾種代價函數

SAD(Sum of Absolute Difference)SAE(Sum of Absolute Error)即絕對誤差和 SATD(Sum of Absolute Transformed Difference)即hadamard變換后再絕對值求和 SSD(Sum of Squared Difference)SSE&am…

Markdown文件導出為HTML的小程序

Markdown文件導出為HTML的小程序為什么做 最近把一些學習經驗記下來,總結成MarkDown文件,不知不覺已經有12篇了。 Sublime Text 的 MarkDown Preview 插件能夠將MarkDown語法轉換為HTML,并提供三種預覽方式:瀏覽器預覽、保存為HTM…

python制作自動回復腳本_python itchat實現微信自動回復的示例代碼

今天在實驗樓發現一個特別好玩的,Python 微信庫itchat,可以實現自動回復等多種功能,好玩到根本停不下來啊,尤其是調戲調戲不懂計算機的,特別有成就感,哈哈!!代碼如下:#codingutf8imp…

pta龜兔賽跑Java_PTA-龜兔賽跑

烏龜與兔子進行賽跑,跑場是一個矩型跑道,跑道邊可以隨地進行休息。烏龜每分鐘可以前進3米,兔子每分鐘前進9米;兔子嫌烏龜跑得慢,覺得肯定能跑贏烏龜,于是,每跑10分鐘回頭看一下烏龜,…

視頻壓縮算法的相關知識

視頻壓縮算法的相關知識MPEG-1MPEG 視頻壓縮編碼后包括三種元素:I幀(I-frames)、P幀(P-frames)和B幀(B-frames)。在MPEG編碼的過程中,部分視頻幀序列壓縮成為I幀;部分壓縮…

安裝MariaDB數據庫(未完成)

1轉載于:https://www.cnblogs.com/centos7/p/5994533.html

python接口開發django_用 Django 開發接口

環境搭建1、pip install django2.2.0一、django-admin startproject UITESTpython manage.py startapp paltform創建Django項目1. 創建方式:#方式1:終端輸入django-admin startproject UITEST#方式2:pycharm中新建django項目在settings.py文件中添加應用…

戒掉dota

立言為證。 每次不想學習想到dota就強迫自己去培養的興趣。 比如看一本喜歡的書;比如去跑個步;比如研究某個興趣點寫個報告;比如寫份隨筆。 轉載于:https://www.cnblogs.com/hongxia/p/3830348.html

java切入式編程顯示屏_C語言嵌入式系統編程修煉之四:屏幕操作

C語言嵌入式系統編程修煉之四:屏幕操作作者:宋寶華 更新日期:2005-07-22漢字處理現在要解決的問題是,嵌入式系統中經常要使用的并非是完整的漢字庫,往往只是需要提供數量有限的漢字供必要的顯示功能。例如,一個微波爐的LCD上沒有必要提供顯…

DIV的邊距屬性在Chrome和IE中的區別

突然間,在Chrome下看起來很整齊的布局,在IE下變成一團糟。為了找出原因,我改動了div的background-color屬性。最后,發現同一個DIV的寬度在IE和Chrome下卻不一樣。這大晚上的,真是怪嚇人滴! 之后&#xff0c…

算法之矩陣計算斐波那契數列

算法之矩陣計算斐波那契數列 本節內容 斐波那契介紹普通方式求解斐波那契矩陣概念矩陣求冪矩陣求解斐波那契1.斐波那契介紹 斐波那契數列有關十分明顯的特點,那是:前面相鄰兩項之和,構成了后一項。即f(n)f(n-1)f(n-2),f(0)0,f(1)f(2)1,推導下…

python中去除字符串中首尾空格的函數_Python中去除字符串首尾特定字符的函數:strip()...

Python中strip()函數的作用是去除一個字符串前導和尾部的特定字符,并返回結果字符串。Python中strip()函數默認是刪除字符串前導和尾部空格,通過設定參數,也可以去除字符串前導和尾部的其它特定字符。strip()函數的語法格式str.strip( [ char…

SeekBar和RatingBar

1. SeekBar的主要屬性 2. OnSeekBarChangeListener 3. RatingBar的主要屬性 4. OnRatingBarChangeListener 1. SeekBar的主要屬性 2. OnSeekBarChangeListener 1 <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"2 xmlns:tools&qu…

用“Web的思想”做PC客戶端

一直在想&#xff0c;用HTML搭建前端頁面這么方便&#xff0c;而且效果這么炫&#xff0c;為什么在PC端的軟件要如此麻煩呢&#xff1f;就連C#也是&#xff0c;更何況C了。 盡管C有DirectUI這樣優秀的圖形庫&#xff0c;但是開發起來仍然非常吃力。C#的WPF雖然工具鏈完善&#…

Java點擊按鈕div縮放_[Java教程]怎樣給div增加resize事件

[Java教程]怎樣給div增加resize事件0 2016-10-31 11:00:04當瀏覽器窗口被調整到一個新的高度或寬度時&#xff0c;就會觸發resize事件,這個事件在window上面觸發,那么如何給div元素增加resize事件&#xff0c;監聽div的高度或寬度的改變呢&#xff1f;某位大神用jquery實現的方…

python判斷題題庫大數據技術_智慧樹_大數據分析的python基礎_搜題公眾號

智慧樹_大數據分析的python基礎_搜題公眾號更多相關問題社會公眾可以查閱煙草專賣行政主管部門的監督檢查記錄。()公民、法人或者其他組織不得利用自動售貨機銷售煙草制品。()煙草廣告中不得有下列情形()。A、社會公益廣告B、遷址、換房、更名等啟事廣告C、表示吸煙有利人體健公…

Java并發中常用同步工具類

為什么80%的碼農都做不了架構師&#xff1f;>>> 同步工具類可以是任何一個對象&#xff0c;只要它根據其自身的狀態來協調線程控制流。阻塞隊列&#xff08;BlockingQueue&#xff09;可以作為同步工具類&#xff0c;其他類型的同步工具類還包括信號量&#xff08;…

Linux平臺Oracle多個實例啟動說明

環境說明:oracle實例1的SID為orcl(為默認啟動的實例),第二個實例的SID為orcl2 啟動步驟&#xff1a; 1&#xff09;啟動數據庫實例完成后&#xff0c;啟動數據庫監聽服務 #lsnrctl start 2&#xff09;切換到需要啟動的數據庫實例下&#xff0c;如下表示啟動的是orcl數據庫…

RTMP協議發送H.264編碼及AAC編碼的音視頻,實現攝像頭直播

RTMP協議發送H.264編碼及AAC編碼的音視頻&#xff0c;實現攝像頭直播 摘要: RTMP協議發送H.264編碼及AAC編碼的音視頻&#xff0c;實現攝像頭直播  RTMP&#xff08;Real Time Messaging Protocol&#xff09;是專門用來傳輸音視頻數據的流媒體協議&#xff0c;最初由Macrome…