Мелкая копия Python автоматически не меняет переменную при изменении другой переменной - PullRequest
1 голос
/ 18 октября 2019

У меня есть фрагмент кода, который должен использовать поверхностное копирование для создания автоматически меняющихся переменных: pos_x и pos_y, когда изменяется pos.

import copy
class AClass:
    def __init__(self):
        self.pos = [1, 2]
        self.pos_x = copy.copy(self.pos[0])
        self.pos_y = copy.copy(self.pos[1])


temp = AClass()
temp.pos[0] = 5
print(temp.pos_x)

Почему выводится 1 вместо 5?

Ответы [ 2 ]

1 голос
/ 18 октября 2019

Потому что то, что делает ваш код, не то, что вы думаете. Мелкая копия списка создаст новый список и добавит ссылки на объекты внутри него.

Дело в том, что у ссылки на два элемента (которые являются числами) есть ссылки на неизменяемый объект 1 и 2, а не на конкретные 1 и 2 внутри вашего списка. Вы можете проверить это, используя идентификатор:

temp = AClass()
id(temp.pos[0])
id(1)

Идентификаторы одинаковы, что означает, что ваш temp.pos [0] указывает на «глобальный» 1.

Если выдействительно хотел сделать что-то похожее на то, что вы думали, без больших изменений (например, с помощью методов для изменения pos), это должно было бы быть что-то вроде этого:

import copy
class AClass:
    def __init__(self):
        self.pos = [[[1]], [[2]]]
        self.pos_x = copy.copy(self.pos[0])
        self.pos_y = copy.copy(self.pos[1])

Затем, copy создаст новый список и вставитссылка на список с 1 там. И изменение t [0] [0] [0] также изменит x [0] [0]. Но это, вероятно, далеко не хороший способ сделать это. И снова вы можете проверить, что идентификаторы t [0] [0] и x [0] одинаковы, поэтому они оба указывают на один и тот же список.

1 голос
/ 18 октября 2019

Последовательность событий была:

  1. Создано temp, что включало присвоение копий элементов от temp.pos до temp.pos_x и temp.pos_y.
  2. Заменитезначение temp.pos.
  3. Вывести значение temp.pos_x.

В этом коде ничего нет, что вызывает pos_x или pos_yизменить при изменении pos.

...