Если срез копирует ссылки, почему это поведение?

1

В соответствии с этим, 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 и изменяет новый объект. В любом месте я могу более подробно ознакомиться с этим поведением?

  • 0
    Задание копирует ссылки тоже. См. Nedbatchelder.com/text/names.html .
  • 2
    b[1]=0 изменяет ссылку, а не ссылочный объект. Так что теперь два списка имеют разные ссылки. Когда вы видите изменения, отраженные в списках, это происходит не потому, что изменение ссылки в b меняет ссылку в a , а потому, что объект, на который ссылаются как a и b изменился. Нарисуйте несколько картинок со стрелками, представляющими ссылки, это действительно помогает.
Показать ещё 4 комментария
Теги:
list
reference
slice

1 ответ

4
Лучший ответ

Предположим, вы начинаете с 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 все еще находится в памяти, возможно, прямо или косвенно ссылаясь на какое-то другое имя, но не через a или b).


С помощью b = a[:] вы создаете новый список, но этот новый список содержит ссылки на один и тот же объект:

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

Теперь, когда вы пишете b[1] = 0, вы не меняете a[1], потому что a и b являются отдельными объектами списка.

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

Сообщение блога Ned Batchelder (и последующее обсуждение PyCon) - отличный обзор модели имени Python.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню