省略号列出[...]并将列表连接到自身

12q*_*2qu 7 python list concatenation

编辑:我原来的例子里不小心.当我A向自己添加列表时,而不是当我向其自身添加包含列表的列表时,行为不会发生.请参阅下面的更正示例.AA


我试图理解省略号列表([...]在列表引用自身时出现和出现的列表)如何在Python 2中工作.

特别是,我想知道为什么,如果A是a list,A = A + A似乎对A += A(和A.append(A))的工作方式不同.

也就是说,你为什么得到:

>>> a = [1, 2]  
>>> a = a + [a]
>>> a  
[1, 2, [1, 2]]
Run Code Online (Sandbox Code Playgroud)

>>> a = [1, 2]  
>>> a += [a]
>>> a
[1, 2, [...]]
Run Code Online (Sandbox Code Playgroud)

(注意,a.append(a)就像后者一样,对我来说似乎有用.)

如果它有助于澄清事情,那么关于这个省略号列表现象的任何其他更一般的信息也将非常受欢迎.

Tim*_*ker 6

编辑:(解决您对该问题的修改引发的其他问题):

a = a + b并且a += b是不一样的操作.前者执行a.__add__(b),后者执行a.__iadd__(b)("就地添加").

两者之间的区别在于前者始终创建一个新对象(并将名称a重新绑定到该新对象),而后者则就地修改对象(如果可以,并且可以使用列表,则可以).

为了说明这一点,只需查看对象的地址:

>>> a = [1, 2]
>>> id(a)
34660104
>>> a = a + [a]
>>> id(a)
34657224
>>> id(a[2])
34660104
Run Code Online (Sandbox Code Playgroud)

"新" a是从头开始构建的,首先从旧列表中获取值a,然后将对旧引用的引用连接到它.

对比如下:

>>> a = [1, 2]
>>> id(a)
34658632
>>> a += [a]
>>> id(a)
34658632
>>> id(a[2])
34658632
Run Code Online (Sandbox Code Playgroud)

(旧答案,解释循环引用):

考虑一下:

>>> a = [1, 2]; a += a
>>> a
[1, 2, 1, 2]
>>> a = [1, 2]; a.extend(a)
>>> a
[1, 2, 1, 2]
>>> a = [1, 2]; a += [a]
>>> a
[1, 2, [...]]
>>> a = [1, 2]; a.append(a)
>>> a
[1, 2, [...]]
Run Code Online (Sandbox Code Playgroud)

那么,总结第一部分:

对于列表,a += a等同于调用就地a.extend(a)修改a,添加在a此操作开始时找到的元素的副本.

相反地,a += [a]对应于a.append(a),两者都创建对列表的引用a(即,一个指向在其存储器地址),并添加到列表中.这构成了所谓的"循环参考".

如果你要查看a那一点的内部表示,它看起来像这样:

a:    Reference to a list object at address 0xDEADBEEF
a[0]: Reference to the integer object "1"
a[1]: Reference to the integer object "2"
a[2]: Reference to the same list object at address 0xDEADBEEF
Run Code Online (Sandbox Code Playgroud)

旧的Python版本(1.5.1之前版本)不够聪明,无法检测到这一点,所以如果你要做一个print a,你就会[1, 2, [1, 2, [1, 2, [1, 2, [1, 2, [1, 2, ...在无限循环中获得等等.从Python 1.5.1开始,解释器检测到这一点,[1, 2, [...]]而不是打印.