列表为例(可变类型容器),直接上代码:
第一种:
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 可能在向你招手!
附赠:求 子集 案例
import copy
def f(sub):
temp_list = [[]]
for x in sub:
for y in copy.deepcopy(temp_list):
y.append(x)
temp_list.append(y)
return temp_list
print(f(list(range(4))))