我在一次编码测试中被问到这个问题,但不知道答案。有人有任何想法吗?
[:]
是 Python 中的切片操作符。
将其放在列表左侧时,可以直接修改列表中的内容而不创建新的引用。
将其放在列表右侧时,可以创建一个包含相同内容的列表副本。
a = b[:]
调用 __getslice__
或 __getitem__
在 b
上,并将结果赋值给 a
。在几乎所有情况下(例如列表、元组和其他序列类型),这会生成一个浅拷贝;我不知道有哪些类没有实现这种行为,但你可能有一个用户定义的类型,它会执行不同的操作。任何先前引用旧值 a
的其他对象将继续引用该旧值。
另一方面,a[:] = b
调用 __setslice__
或 __setitem__
来替换 a
的子集合为序列 b
中的元素。在这种情况下,如果 a
的序列类型是良好的,由于没有端点的范围 :
表示整个序列,因此将替换 a
的全部内容。不同之处在于,不可变类型(例如元组)将不允许你执行 __setslice__
(例如通过抛出 TypeError
异常)。任何先前引用 a
的其他对象也将被更新,因为正在修改底层对象。
对于可变类型(例如 list
),a = b[:]
的结果与 a[:] = b
相同,因为 a
将是 b
的浅拷贝;对于不可变类型(例如 tuple
),a[:] = b
是无效的。对于行为不良的用户定义类型,则情况未知。还有一个区别是其他引用相同对象的对象 -- 通过 a = b[:]
,它们引用原始值(a
),但通过 a[:] = b
,它们引用修改后的对象(b
的浅拷贝)。
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
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
不再共享同一个对象。
就速度而言,a[:] = b
比a = b[:]
稍快一些。前者不需要创建新的列表对象,它只需修改现有列表即可。其中很大一部分原因是它可以重用已经拥有的列表内存,而不是分配新的内存。
a[:] = b
结构。 - Adam Rosenfield