經驗拾憶(純手工)=> 關於深拷貝/淺拷貝的代碼,你,是否注意過?

列表爲例(可變類型容器),直接上代碼:

第一種:

a = [[1,2], [3,4]]
[_.append(666) for _ in a]        # 原生列表  (for 也是一樣的,圖個方便,用了推導式)
print(a)

>> [[1, 2, 666], [3, 4, 666]]

第二種:

a = [[1,2], [3,4]]
[_.append(666) for _ in a[:]]     # 新增操作: 對整個列表切片自爆
print(a)

>> [[1, 2, 666], [3, 4, 666]]

第三種:

a = [[1,2], [3,4]]
[_.append(666) for _ in copy.copy(a)]      # 新增操作: 對整個列表使用淺拷貝API
print(a)

>> [[1, 2, 666], [3, 4, 666]]

------------------ 分割線-------------------------

第四種:

a = [[1,2], [3,4]]
[_.append(666) for _ in copy.deepcopy(a)]      # 新增操作: 整個列表使用深拷貝API
print(a)

>> [[1, 2], [3, 4]]

第五種:(注意 和 第二種 對比)

a = [[1,2], [3,4]]
[_[:].append(666) for _ in a]      # 新增操作:對即將操作的子列表切片自爆
print(a)

>> [[1, 2], [3, 4]]

第六種:(注意 和 第三種 對比)

a = [[1,2], [3,4]]
[copy.copy(_).append(666) for _ in a]   # 新增操作:對即將操作的子列表 使用淺拷貝API
print(a)

>> [[1, 2], [3, 4]]

提醒0

多級容器需謹慎 (雖然多級 純 元組是不可變類型,你想弄也弄不動它~~~)
但是這種情況,你還是需要注意:

a = ([1,2], [3,4])
# 裏面的列表依然是可變的, 這算是剛入門的基礎。但還應該留意

提醒一

除了 deepcopy, 其他操作都是淺拷貝。
如果你喜歡使用 [::] , [:] 這種切片拷貝, 那麼更應該注意一下上述案例問題。

提醒二

也許你看上述代碼很一般。甚至沒有任何感覺。
但是當你把子列表當作中間值(任意操作變換), 再提醒一次 ===> 作爲 中間值(或者說臨時值)使用時。
你的BUG可能在向你招手!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章