我被问到这是一个编码测试而且不知道答案。有人有什么想法吗?
答案 0 :(得分:8)
[:]
是切片运算符。
当它在左侧时,它会覆盖列表的内容而不创建新的引用。
当它在右侧时,它会创建具有相同内容的列表副本。
答案 1 :(得分:2)
a = b[:]
拨打b
上的__getslice__
或__getitem__
,并将结果分配给a
。在几乎所有情况下(例如列表,元组和其他序列类型),这都是序列的浅表副本;我不知道任何没有实现该行为的类,但是您可以使用用户定义的类型来执行不同的操作。之前引用旧值a
的任何其他对象将继续引用该旧值。
a[:] = b
调用__setslice__
或__setitem__
将a
的元素子集替换为序列b
的元素。在这种情况下,如果a
的序列类型表现良好,则会替换整个a
,因为没有端点的范围:
表示整个序列。这里的区别在于,诸如元组之类的不可变类型将不允许您执行__setslice__
(例如,通过抛出TypeError
异常)。之前引用a
的任何其他对象也将被更新,因为底层对象正在被修改。
对于list
等可变类型,a = b[:]
的结果与a[:] = b
相同,因为a
将是b
的浅层副本;对于tuple
等不可变类型,a[:] = b
无效。对于行为不当的用户定义类型,所有投注均已关闭。对于与a
引用同一对象的其他对象所发生的情况也有区别 - 使用a = b[:]
,它们引用原始值(a
),但{{1}它们引用了修改过的对象(a[:] = b
的浅表副本)。
答案 2 :(得分:1)
在这两种情况下,您最终都会将列表a
作为列表b
的副本。但是用于实现这一目标的方法已经发生了变化。
a[:] = b
修改列表a
,使其与b
具有相同的元素
a = b[:]
生成一个新列表,该列表是b
的副本,并替换列表a
区别在于我们是否修改了现有列表或创建了新列表。
要看到差异:
a = range(3)
b = range(4)
c = a # c and a now share the same list
a[:] = b
print "a", a
print "b", b
print "C", c
所有三个列表都会打印出来。 C和a共享同一个对象,因此当a
被修改时,c
a = range(3)
b = range(4)
c = a # c and a now share the same list
a = b[:]
print "a", a
print "b", b
print "C", c
现在c不会打印出与a相同的内容。分配后,a
和c
不共享同一个对象。
Speedwise,a[:] = b' is probably a little faster then
a = b [:]`。第一种形式不必创建新的列表对象,它只能修改现有列表。其中很大一部分是它可以重用已经由列表拥有的内存,而不是分配新的内存。