【问题标题】:If slice copies references why this behavior?如果切片副本引用为什么会出现这种行为?
【发布时间】:2018-07-10 20:52:37
【问题描述】:

根据this,python 在切片时复制引用。我尝试了以下方法:

>>> a=[1,2,3]
>>> b=a[:]
>>> b[1]=0
>>> a
[1, 2, 3]
>>> b
[1, 0, 3]
>>> map(id,a)
[14508376, 14508352, 14508328]
>>> map(id,b)
[14508376, 14508400, 14508328]

为什么b[1]=0 不会改变a[1](如果b[1] 确实是对同一对象的引用,可能会是这种情况)?相反,它似乎生成了一个新的引用/id 并更改了新对象。我可以在哪里更详细地了解此行为?

【问题讨论】:

  • Assignment 也会复制引用。见nedbatchelder.com/text/names.html
  • b[1]=0 更改引用,而不是引用的对象。所以现在这两个列表有不同的引用。当您看到更改反映在列表中时,这并不是因为 b 中引用的更改更改了 a 中的引用,而是因为 ab 中引用的对象都已更改。画一些带有箭头的图片代表参考,它确实有帮助。
  • @user2357112 是的,但行为不同
  • 与什么不同?如果您是这样想的话,这肯定与复制引用的行为没有什么不同。
  • @user2357112 我的意思是c=a(赋值),c[1]=0 导致a 成为[1,0,3],不像使用切片时a[:]

标签: python list reference slice


【解决方案1】:

假设您以a = [1,2,3] 开头。在 Python 的数据模型中,这意味着 a 指的是内存中的一个对象:

a -> [ * | * | * ]
       |   |   |
       v   v   v
       1   2   3

使用b = a,您只需将另一个名称指向同一个对象:

a -> [ * | * | * ] <- b
       |   |   |
       v   v   v
       1   2   3

b[1] = 0 更改相同的引用 a[1] = 0 将:

           0
           ^
           |
a -> [ * | * | * ] <- b
       |       |
       v       v
       1   2   3

2 仍在内存中,可能通过其他名称直接或间接引用,但不再通过ab 引用。)


使用b = a[:],您将创建一个新的列表,但该新列表包含对同一对象的引用:

a -> [ * | * | * ]
       |   |   |
       v   v   v
       1   2   3
       ^   ^   ^
       |   |   |
b -> [ * | * | * ]

现在,当您编写 b[1] = 0 时,您不会更改 a[1],因为 ab 是不同的列表对象。

a -> [ * | * | * ]
       |   |   |
       v   v   v
       1   2   3
       ^       ^
       |       |
b -> [ * | * | * ]
           |
           v
           0

Ned Batchelder 的 blog post(以及后续的 PyCon talk)是对 Python 名称模型的出色概述。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    • 2019-12-29
    • 2018-07-27
    • 2014-06-07
    • 1970-01-01
    相关资源
    最近更新 更多