成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

序列賦值引發的Python列表陷進

開發 后端
++是指把兩個序列的元素拼接在一起。通常+號兩側的序列由相同類型的數據所構成,在拼接的過程中,兩個被操作的序列都不會被修改,Python會新建一個包含同樣類型數據的序列作為拼接的結果。

[[384843]]

本文轉載自微信公眾號「dongfanger」,作者dongfanger。轉載本文請聯系dongfanger公眾號。

序列賦值是Python默認操作,如果使用不當,有可能會掉入語法陷阱。

+

+是指把兩個序列的元素拼接在一起。通常+號兩側的序列由相同類型的數據所構成,在拼接的過程中,兩個被操作的序列都不會被修改,Python會新建一個包含同樣類型數據的序列作為拼接的結果。比如:

  1. a = [1] 
  2. b = [2] 
  3. c = a + b 
  4. print(a, b, c) 
  5. print(id(a), id(b), id(c)) 

結果為:

  1. [1] [2] [1, 2] 
  2. 2409610524480 2409610523520 2409610523648 

*

如果想要把一個序列復制幾份然后再拼接起來,更快捷的做法是把這個序列乘以一個整數。同樣,這個操作會產生一個新序列:

  1. >>> l = [1] 
  2. >>> l * 5 
  3. [1, 1, 1, 1, 1] 
  4. >>> 5 * "a" 
  5. 'aaaaa' 

+和*都遵循這個規律,不修改原有的操作對象,而是構建一個全新的序列。

列表套列表的陷進

猜猜這個結果會是啥:

  1. x = ["x"
  2. my_list = [x] * 3 
  3. print(my_list)  # [['x'], ['x'], ['x']] 
  4.  
  5. x2 = my_list[2] 
  6. x2[0] = "y" 
  7. print(my_list) 

講道理,應該是[['x'], ['x'], ['y']],但是錯了,實際是:

  1. [['y'], ['y'], ['y']] 

Unbelievable!給my_list的最后一個元素的列表賦值,結果所有三個元素的列表都被賦值了!這反映出my_list這三個元素不是3個列表,而是3個列表引用,指向了同一個相同的列表。相當于:

  1. x = ["x"
  2. my_list = [] 
  3. for i in range(3): 
  4.     my_list.append(x)  # 追加相同對象 
  5.  
  6. x2 = my_list[2] 
  7. x2[0] = "y" 
  8. print(my_list)  # [['y'], ['y'], ['y']] 

每次都追加了同一個對象到my_list。如果想生成3個不同列表,那么需要在每次迭代中新建列表:

  1. my_list = [] 
  2. for i in range(3): 
  3.     x = ["x"]  # 新建列表 
  4.     my_list.append(x) 
  5.  
  6. x2 = my_list[2] 
  7. x2[0] = "y" 
  8. print(my_list)  # [['x'], ['x'], ['y']] 

這樣就符合預期了。可以用列表推導簡化代碼:

  1. x = ["x"
  2. my_list = [x for i range(3)] 
  3.  
  4. x2 = my_list[2]   
  5. x2[0] = "y" 
  6. print(my_list)  # [['x'], ['x'], ['y']] 

教訓:

新建列表中的列表,使用列表推導,不要使用*運算符。

如果a * n這個語句中,序列a里的元素是對其他可變對象的引用的話,就需要格外注意了,這可能不是你想要的效果。

+=

a += b雖然意思是a = a + b,但是它背后的特殊方法是__iadd__,如果一個類沒有實現這個方法的話,Python才會退一步調用__add__。__iadd__方法會直接在原對象中追加,__add__方法會先生成新對象再賦值。

*=

+=的這些概念也適用于*=,只是后者對應的是__imul__。追加還是新對象,在作用到可變序列和不可變序列時效果明顯,示例:

  1. # 可變序列,追加 
  2. >>> l = [1, 2, 3] 
  3. >>> id(l) 
  4. 2135319475136 
  5. >>> l *= 2 
  6. >>> l 
  7. [1, 2, 3, 1, 2, 3] 
  8. >>> id(l) 
  9. 2135319475136  # id一樣 
  10.  
  11. # 不可變序列,新對象 
  12. >>> t = (1, 2, 3) 
  13. >>> id(t) 
  14. 2135322139520 
  15. >>> t *= 2 
  16. >>> id(t) 
  17. 2135321695424  # id不一樣 

元組套列表的陷進

  1. >>> t = (1, 2, [30, 40]) 
  2. >>> t[2] += [50, 60] 

猜猜會發生下面4種情況中的哪一種?a.t變成(1, 2, [30, 40, 50, 60])b.因為tuple不支持對它的元素賦值,所以會拋出TypeError異常c.以上兩個都不是d.a和b都是對的因為元組不能賦值,所以我會毫不猶豫的選擇b。但實際上答案是d!a和b都是對的,既會賦值成功,也會報錯:

  1. >>> t = (1, 2, [30, 40]) 
  2. >>> t[2] += [50, 60] 
  3. Traceback (most recent call last): 
  4.   File "<input>", line 1, in <module> 
  5. TypeError: 'tuple' object does not support item assignment 
  6. >>> t 
  7. (1, 2, [30, 40, 50, 60]) 

Oh No!為什么?一、賦值成功,因為t[2]指向的是一個可變對象(列表[30, 40]),可變對象是能賦值的。二、報錯,因為可變對象賦值給了不可變對象(元組t),不可變對象不能賦值。

寫成t[2].extend([50, 60])能避免這個異常。

教訓:

  1. 不要把可變對象放在元組里面。
  2. +=不是一個原子操作,雖然拋出了異常,但還是完成了操作。

這位巴西作者說到,在他15年的Python生涯中,他還沒見過誰在這個地方吃過虧。

小結

本文分別介紹了+、*和列表套列表的陷阱,+=、*=和元組套列表的陷阱,并分別得出了教訓。這是動態語言的弊端,在運行后才能知道有沒有類型錯誤,只能積累代碼經驗來避免。魚與熊掌不可兼得,在享受Python語法簡潔的便利同時,也得付出運行報錯排查麻煩的代價。

 

參考資料:《流暢的Python》

 

責任編輯:武曉燕 來源: dongfanger
相關推薦

2022-03-03 17:06:24

序列類型新增元素Python

2021-09-02 07:52:18

算法大數據個人信息保護

2021-05-28 05:49:28

Python數據結構與算法bisect

2024-07-12 12:01:37

Python代碼多重賦值

2009-03-13 16:39:16

Linux開源改變

2021-01-11 05:30:04

Boot 單機片

2023-07-05 07:21:34

時間序列學習框架模型

2009-06-19 08:29:36

Windows 7微軟操作系統

2015-02-04 14:36:07

格式串漏洞Ghost漏洞安全漏洞

2011-10-17 08:29:33

Ubuntu 11.1思考

2012-07-05 09:54:04

Amazon宕機

2020-11-11 10:00:13

NAT性能內核

2013-06-20 09:59:12

Javascriptvar

2011-02-28 09:31:30

HashtableHashMap

2013-03-05 10:05:52

2022-05-27 07:51:07

自定義無序列表CSS

2020-03-02 00:32:08

Python列表for循環

2013-04-16 10:48:04

Python序列

2017-05-24 15:50:08

PythonCPython

2010-03-15 09:47:43

Python DNA序
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 在线视频国产一区 | 毛片黄片免费看 | 久久一区二区三区电影 | 亚洲精品在线视频 | 亚洲午夜一区二区 | 色婷婷一区二区三区四区 | 一级黄色片一级黄色片 | 欧美日本一区二区 | 韩日三级| h在线免费观看 | 日本成人在线免费视频 | 欧美日韩不卡在线 | 国产在线观看一区二区三区 | 午夜一区二区三区视频 | 精品一区二区在线观看 | 美女视频一区 | 久久综合久久综合久久 | 精彩视频一区二区三区 | 亚洲三区视频 | 久久久久久久综合色一本 | 美女福利网站 | 日本一本视频 | 精品成人在线 | 久久精品二区亚洲w码 | 在线视频 中文字幕 | 日韩国产精品一区二区三区 | 男人的天堂亚洲 | 久久久久国产精品一区二区 | 手机看片在线播放 | 91毛片网 | 亚洲天堂免费在线 | 国产视频一区二区 | 精品自拍视频 | 国产真实精品久久二三区 | 久久久久久国产精品免费 | 久久久久久中文字幕 | 91精品国产乱码久久久久久 | 天天干精品 | 在线欧美一区 | 国产成人免费视频 | 国产精品我不卡 |