日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python中的可变数据类型有列表和元组_Python中列表的 += 和 .extend() 的异同

發布時間:2023/12/10 python 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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有非常明確的解答了,推薦閱讀:

總結

以上是生活随笔為你收集整理的python中的可变数据类型有列表和元组_Python中列表的 += 和 .extend() 的异同的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。