a [:] = b和a = b [:]之间的区别? (蟒蛇)

时间:2011-08-11 22:07:22

标签: python sequence slice

我被问到这是一个编码测试而且不知道答案。有人有什么想法吗?

3 个答案:

答案 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相同的内容。分配后,ac不共享同一个对象。

Speedwise,a[:] = b' is probably a little faster then a = b [:]`。第一种形式不必创建新的列表对象,它只能修改现有列表。其中很大一部分是它可以重用已经由列表拥有的内存,而不是分配新的内存。