我有一个名为mylist
有什么区别
newlist = mylist
和
newlist = mylist[:]
似乎后者更安全,因为它不会基于对mylist
的任何操作而使newlist
发生突变
`
答案 0 :(得分:2)
第一个只为列表创建另一个名称。它仍然是相同的列表。
这意味着突变newlist
也会突变mylist
。
>>> mylist = [1, 2, 3]
>>> newlist = mylist
>>> newlist.append(4)
>>> mylist
[1, 2, 3, 4]
第二个示例实际上创建了一个列表的副本,一个实际的新列表。
>>> mylist = [1, 2, 3]
>>> newlist = mylist[:]
>>> newlist.append(4)
>>> newlist
[1, 2, 3, 4]
>>> mylist
[1, 2, 3]
您几乎没有理由为同一个对象使用两个名称,因为这可能会造成混淆并导致突变错误。
变异错误是指代码的某些部分需要某个对象(例如函数func1
),而代码的某些其他部分则需要先进行突变,例如函数func2
。如果func1
期望对象处于初始状态,那么追踪突变发生的位置可能非常繁琐。
示例:
obj = [list of data]
same_obj = obj
func2(same_obj) # mutates the object
# hundreds of lines of code
func1(obj) # needs the initial state of the object
在上面的示例中,最好将func2
的副本传递给obj
。由于第一行和最后一行之间发生了很多事情,因此追踪突变错误可能非常繁琐。
答案 1 :(得分:0)
区别在于:第一个在本地命名空间中创建(或重新绑定)引用同一mylist
实例的另一个名称。您可以将其视为别名。第二个创建mylist
的浅表副本。
此行:
newlist = mylist
是可怕的Python。因为这不是变量名所暗示的“新列表” ,所以只是为同一列表添加了另一个名称。
这是可以接受的:
mylist_again = mylist
是否最好使用mylist[:]
切片,这完全取决于上下文。有时您想要一个副本,有时您想要另一个对现有数据的引用。
后者似乎更安全,因为它不会基于对newlist的任何操作而使mylist变异
那不是完全正确的,因为切片只是一个浅表副本。新列表可能仍处于共享状态:
>>> mylist = [0, [1]]
>>> newlist = mylist[:]
>>> newlist[0] = 123
>>> newlist[1][0] = 456
>>> mylist
[0, [456]]
>>> newlist
[123, [456]]
同样,浅表副本是否足够取决于数据。如果您使用嵌套数据而浅表副本不够用,或者应该复制可变元素,则可以使用copy.deepcopy
。