Почему эта переменная изменяется? - PullRequest
2 голосов
/ 14 августа 2010
tokens_raw = {"foo": "bar"}
tokens_raw_old = { }
while not tokens_raw == tokens_raw_old:
    tokens_raw_old = tokens_raw
    # while loop that modifies tokens_raw goes here;
    # tokens_raw_old is never referenced
    print tokens_raw_old == tokens_raw

Это выводит True после первого раза по какой-то причине. tokens_raw_old имеет те же данные, что и tokens_raw, даже после изменения только tokens_raw. Я где-то допустил глупую ошибку или проблема заключается во втором цикле while (который, опять же, никогда не ссылается на tokens_raw_old)? Если нет очевидных ошибок, я выложу больше кода.

1 Ответ

7 голосов
/ 14 августа 2010

tokens_raw_old = tokens_raw означает: создайте новую ссылку с именем token_raw_old на такой же объект, к которому относится имя tokens_raw в данный момент. Это тот же объект, , а не копия объекта! Таким образом, изменения в этом единственном объекте, сделанные с помощью одной из ссылок, очевидно, также влияют на тот же объект при рассмотрении с помощью другой ссылки.

Если вам нужна копия, попросите ее! Например, поскольку tokens_raw является диктатом с неизменяемыми значениями (и ключами, но это часто встречается в диктовках):

tokens_raw_old = tokens_raw.copy()

будет достаточно. Идентично (просто вопрос стиля), так же будет

tokens_raw_old = dict(tokens_raw)

(сделать копию, «вызывая тип как конструктор копирования»), концепция, которая привлекает программистов на C ++, и я очень люблю эту форму; -).

Если вам нужно охватить общий случай (tokens_raw может иметь множество различных типов или значения в нем могут быть изменены):

import copy

tokens_raw_old = copy.deepcopy(tokens_raw)

Это может быть довольно медленно, но, «когда вам это нужно, вам это нужно» - это делает копию объекта deep , то есть он не просто копирует контейнер, но также все содержащиеся объекты (рекурсивно, если контейнер содержит другие контейнеры - скажем, что в три раза быстрее ...; -).

Не каждый объект может быть скопирован (глубоко или поверхностно) - например, объект открытого файла не может быть скопирован (вам нужны другие подходы, если у вас когда-либо есть такие странные, сложные потребности). Но для диктата со строками в качестве ключей и значений достаточно простых подходов, которые я упомянул в начале этого ответа, и они тоже будут довольно быстрыми; -).

...