最近在改baseline的代码,发现一个以前不知道的python知识(我的python基础还是太差了!)。
场景重现
list1 = [1, 2, 3]
list2 = list1
这时候无论修改 list1 还是 list2 ,另一个 list 变量内容也会被改变!
如
python
#####输入
def function(list0):
list10 = list0
list10.append(2)
print(f"list0 = {list0}")
if __name__ == '__main__':
list3 = list1
temp = len(list1)
list3.append(19)
list1.extend(list2)
function(list1)
print(f"list3 = {list3}")
print(f"temp = {temp}")
print(f"len(list1) = {len(list1)}")
#####输出
list0 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 19, 10, 11, 2]
list3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 19, 10, 11, 2]
temp = 9
len(list1) = 13
在上面的代码中,无论是append操作还是extend操作,亦或是调用函数都对改变另外一个列表变量的内容!
这种情况是因为在 Python 中,赋值操作实际上是将对象的引用从一个变量传递到另一个变量。当你执行 list3 = list1 时,list3 实际上引用了和 list1 相同的列表对象。因此,当你修改 list1 时,list3 也会发生相应的变化,反之亦然。
所以说,当你将一个列表赋值给另一个变量时,实际上是将对列表的引用复制给了新变量,而不是复制列表本身。这种行为称为浅拷贝。
避免问题的方法
如果你想要避免这种情况,你可以使用深拷贝来创建列表的副本。深拷贝会创建一个新的对象,其中包含原始列表中所有元素的副本。你可以通过 copy 模块中的 deepcopy 函数来实现深拷贝。
python
#####输入
from copy import deepcopy
list1 = [1,2,3,4,5,6,7,8,9]
list2 = [10,11]
def function(list0):
list10 = list0
list10.append(2)
print(f"list0 = {list0}")
if __name__ == '__main__':
list3 = deepcopy(list1)
temp = len(list1)
list3.append(19)
print(f"list1 = {list1}")
list1.extend(list2)
function(list1)
print(f"list3 = {list3}")
print(f"temp = {temp}")
print(f"len(list1) = {len(list1)}")
#####输出
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
list0 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 2]
list3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 19]
temp = 9
len(list1) = 12
需要注意的是,像temp = len(list1)这样的语句不会受到影响,因为它只取决于当时的 len(list1) 值,不受 list1 动态变化所影响!