Странность переменной Python? - PullRequest
       10

Странность переменной Python?

6 голосов
/ 01 сентября 2010

Что происходит с моей переменной Python?old_pos похоже связано с pos:

Код:

pos = [7, 7]
direction = [1, 1]
old_pos = pos
print 'pos     = '+str(pos)
print 'old_pos = '+str(old_pos)
pos[0] += direction[0]
pos[1] += direction[1]
print 'pos     = '+str(pos)
print 'old_pos = '+str(old_pos)

Вывод:

pos     = [7, 7]
old_pos = [7, 7]
pos     = [8, 8]
old_pos = [8, 8]

Однако, если я заменю old_pos = pos с old_pos = tuple(pos) или даже old_pos = list(pos), у меня нет этой проблемы:

pos     = [7, 7]
old_pos = [7, 7]
pos     = [8, 8]
old_pos = [7, 7]

Ответы [ 5 ]

12 голосов
/ 01 сентября 2010

Когда вы говорите old_pos = pos, вы не создаете копию pos, а просто делаете еще одну ссылку на тот же список.Если вам нужны два списка, которые ведут себя независимо, вам нужно сделать копию, например, используя функцию list(pos), как вы упомянули, или используя обозначение среза pos[:].

7 голосов
/ 01 сентября 2010

old_pos = pos не создает копию объекта, на который ссылается имя pos, скорее он создает вторую ссылку с именем old_pos на тот же объект.Действия, выполненные для pos, влияют на тот же объект, на который ссылается old_pos.Точно так же имена «Стивен» и «Мистер Румбальский» относятся ко мне.Если вы ударите Стивена по лицу, мистер Румбальски будет ранен, потому что два имени относятся к одному и тому же объекту - мне.

Вот 3 способа сделать реальную копию вместо второй ссылки:

Использование обозначения среза

old_pos = pos[:]

Использование конструктора списка

old_pos = list(pos)

Использование модуля копирования

from copy import copy
old_pos = copy(pos)

Обратите внимание, что все эти копии мелкиекопии, что в этом случае хорошо.Чтобы узнать разницу между мелкой копией и глубокой копией, прочитайте документацию модуля копирования .

3 голосов
/ 01 сентября 2010

рекурсивно верно по поводу причины.Вы можете видеть, что они имеют идентичные адреса памяти:

>>> pos = [7, 7]
>>> old_pos = pos
>>> id(pos)
4299304472
>>> id(old_pos)
4299304472

Это называется передача по ссылке , а не передача по значению.Вы также можете исправить эту ситуацию, используя модуль copy.

>>> from copy import copy
>>> pos = [7, 7]
>>> old_pos = pos
>>> id(pos)
4299304472
>>> id(old_pos)
4299304472
>>> old_pos = copy(pos)
>>> id(old_pos)
4299349240
3 голосов
/ 01 сентября 2010

old_pos похоже связано с pos

Правильно - это:

old_pos = pos

делает old_pos, а pos указывают на один и тот же список. Он не создает новую копию pos.

0 голосов
/ 25 января 2016

В дополнение к вышеупомянутым комментариям, некоторые дополнительные шаги должны быть предприняты в случае многомерных массивов. Например, если у вас есть двумерный массив a = [[0,1,2],[3,4],[5,6,7,8]], код b = a не будет создавать независимую копию. Однако это создаст другую ссылку на ссылки тех же одномерных списков в двумерном списке. Чтобы решить эту проблему, вы должны использовать один из вышеупомянутых методов для каждого списка в двумерном списке. Например, b = [i[:] for i in a] создаст независимую копию списка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...