【问题标题】:Ellipsis lists [...] and concatenating a list to itself [duplicate]省略号列表[...]并将列表连接到自身[重复]
【发布时间】:2012-04-04 17:01:36
【问题描述】:

编辑:我最初的例子很粗心。该行为不是在我将列表A 添加到自身时发生,而是在我将列表包含列表A 添加到A 本身时发生。请参阅下面的更正示例。


我试图了解省略号列表(那些显示为 [...] 并在您有列表引用时出现的列表)在 Python 2 中的工作原理。

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

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

>>> a = [1, 2]  
>>> a = a + [a]
>>> a  
[1, 2, [1, 2]]

对比

>>> a = [1, 2]  
>>> a += [a]
>>> a
[1, 2, [...]]

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

如果它有助于澄清事情,也将非常感谢有关此省略号列表现象的任何其他更一般的信息。

【问题讨论】:

  • a = [1, 2]; a+=a 将生成[1, 2, 1, 2],而不是[1, 2, [1, 2]。请参阅重复的问题。
  • 所谓的重复不讨论省略号列表根本
  • 我也不懂近距离投票。指针的概念对python很重要,值得解释一下。

标签: python list concatenation


【解决方案1】:

编辑:(以解决您对问题的编辑引起的其他问题):

a = a + ba += b 不是同一个操作。前者执行a.__add__(b),后者执行a.__iadd__(b)(“就地添加”)。

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

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

>>> a = [1, 2]
>>> id(a)
34660104
>>> a = a + [a]
>>> id(a)
34657224
>>> id(a[2])
34660104

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

对比:

>>> a = [1, 2]
>>> id(a)
34658632
>>> a += [a]
>>> id(a)
34658632
>>> id(a[2])
34658632

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

考虑一下:

>>> 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, [...]]

所以,总结第一部分:

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

相反,a += [a] 对应于a.append(a),两者都创建对列表a 的引用(即指向其在内存中的地址的指针)并将 that 添加到列表中。这构成了所谓的“循环引用”。

如果您当时查看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

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

【讨论】:

    【解决方案2】:

    考虑以下几点:

    In [179]: a = [1, 2]
    
    In [180]: a+=a
    
    In [181]: a
    Out[181]: [1, 2, 1, 2]
    
    In [182]: a.append(a)
    
    In [183]: a
    Out[183]: [1, 2, 1, 2, [...]]
    
    In [184]: a[5]
    -----------------------------------------------
    IndexError                                Trace
    C:\Users\Marcin\Documents\oneclickcos\oneclickc
    ----> 1 a[5]
    
    IndexError: list index out of range
    
    In [185]: a[4]
    Out[185]: [1, 2, 1, 2, [...]]
    
    In [186]: a[3]
    Out[186]: 2
    
    In [187]: a[4]
    Out[187]: [1, 2, 1, 2, [...]]
    
    In [188]: a
    Out[188]: [1, 2, 1, 2, [...]]
    
    In [189]: a[4][3]
    Out[189]: 2
    
    In [190]: a[4][4]
    Out[190]: [1, 2, 1, 2, [...]]
    
    In [191]: a[4][5]
    -----------------------------------------------
    IndexError                                Trace
    C:\Users\Marcin\Documents\oneclickcos\oneclickc
    ----> 1 a[4][5]
    
    IndexError: list index out of range
    
    In [192]: a[4][4]
    Out[192]: [1, 2, 1, 2, [...]]
    
    In [193]: a = [1, 2]
    
    In [194]: a+=a
    
    In [195]: a
    Out[195]: [1, 2, 1, 2]
    
    In [196]: a
    Out[196]: [1, 2, 1, 2]
    
    In [197]: a
    Out[197]: [1, 2, 1, 2]
    
    In [198]: a.append(a)
    
    In [200]: a
    Out[200]: [1, 2, 1, 2, [...]]
    
    In [201]: a.append(a)
    
    In [202]: a
    Out[202]: [1, 2, 1, 2, [...], [...]]
    
    In [203]: a[4]
    Out[203]: [1, 2, 1, 2, [...], [...]]
    
    In [204]: a[5]
    Out[204]: [1, 2, 1, 2, [...], [...]]
    
    In [205]: id(a)
    Out[205]: 64692680L
    
    In [206]: id(a[5])
    Out[206]: 64692680L
    
    In [207]: id(a[4])
    Out[207]: 64692680L
    
    In [208]: id(a) == id(a[4]) and id(a[4]) == id(a[5])
    Out[208]: True
    

    首先请注意+= 不会创建省略号列表。

    其次,可以看出省略号列表表示访问该插槽将返回完全相同的列表 - 省略号列表表示指向外部列表的指针(或者,几乎可以肯定一个外部列表,如果有不止一层嵌套)。

    【讨论】:

      【解决方案3】:

      这是因为a = a + a 对应于a.extend(a) 哪个"Extend the list by appending all the items in the given list"。另一种看待它的方式是+ 运算符导致"the concatenation of s and t"

      这与a += a 形成对比,a.append(a) 对应于"adds an item at the end of the list"

      希望能澄清事情。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-11
        • 2012-07-31
        • 1970-01-01
        • 1970-01-01
        • 2013-09-03
        • 2022-11-08
        • 2017-01-21
        • 2019-01-05
        相关资源
        最近更新 更多