我在一个程序中使用列表,但我不理解以下行为。我已经开始了解易变性以及它如何影响变量赋值,但我不认为这里有问题:
class Test:
def __init__(self, list_n):
list_a = list_n[:]
list_b = list_n[:]
print(list_a is list_b) # Prints False
print(list_a is list_n) # Prints False
print(list_b is list_n) # Prints False
list_a[0][0] = 1
print(list_a) # Both of these print [[1,0,0][0,0,0][0,0,0]]
print(list_b)
def main():
list_n = [[0,0,0],[0,0,0],[0,0,0]]
test = Test(list_n)
if __name__ == '__main__': main()
list_a
和{
为什么不用切片表示法复制我的列表?在
您的示例不起作用的原因是您只对
list_n
进行了一个浅拷贝。列表的浅拷贝只复制“顶层”列表。浅层复制列表不会复制子列表。通过在list
(list.copy()
)上调用copy()
或使用切片表示法(list[:]
)来生成列表的浅拷贝。在在C级别,当对列表元素执行浅层复制时,指向列表的指针(称为}都包含指向相同子列表的指针。在
PyObject
s)将从一个列表复制到另一个列表。但是,每个子列表的实际指针不会被复制,因此list_a
和{简单地说,您从来没有复制过}仍然包含指向相同子列表的指针。可以通过使用^{} 创建} :
list_n
中的每个子列表,因此list_a
和{list_n
的“deepcopy”—原始列表中每个子列表的副本,而不考虑嵌套级别—使用^{我应该什么时候使用
deepcopy()
?在使用
deepcopy()
的最大缺点之一是“深度复制”浅嵌套列表需要大量时间。在如果你的列表只是浅层嵌套的(2到3层深),你应该简单地使用嵌套列表理解来代替
^{pr2}$deepcopy()
。使用此方法将大大提高效率(感谢as@jornsharpe指出这一点):通过使用标准库中的^{} 模块可以观察到使用此方法获得的效率:
^{3}$但是,如果您的列表更深入,那么应该选择使用
deepcopy()
,即使它看起来有点庞大。人们通常不需要牺牲可读性而非效率。此外,当列表理解变得越来越复杂时,deepcopy()
上的效率开始变小。在为什么
deepcopy()
这么慢?在之所以
deepcopy()
比大多数其他方法慢得多(感谢@Felix的询问),是因为deepcopy()
比简单的列表理解要做更多的工作。与列表理解不同,deecopy()
必须在任意嵌套的列表上工作,可能有许多层次的嵌套。因此,在浅层嵌套的列表中使用它是一种极端的过度杀戮,并且会导致执行时间慢得多。在为了更好地了解
deepcopy()
在幕后做了什么,您可以查看一下函数的源代码,因为它是open source and available to the public for viewing。在相关问题 更多 >
编程相关推荐