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
)?如果没有明显错误,我会发布更多代码。
答案 0 :(得分:7)
tokens_raw_old = tokens_raw
表示:为此名称token_raw_old
引用的相同对象创建一个名为tokens_raw
的新引用。它是相同的对象,不是对象的副本!因此,当通过另一个引用进行检查时,通过其中一个引用对此唯一对象进行的更改显然也会影响同一个对象。
如果您想要副本,请索取副本!例如,因为tokens_raw
是一个带有不可变值的字典(和键,但在dicts中很常见):
tokens_raw_old = tokens_raw.copy()
就足够了。相同(只是一个风格问题),
也是如此tokens_raw_old = dict(tokens_raw)
(通过“将类型称为复制构造函数”来制作副本,这是一个吸引C ++程序员的概念 - 我就是其中之一,所以我非常喜欢这种形式; - )。
如果您需要涵盖一般情况(tokens_raw
有许多可能的不同类型,或者其中的值可能会被修改):
import copy
tokens_raw_old = copy.deepcopy(tokens_raw)
这可能很慢,但是,“当你需要它时,你需要它” - 它会生成一个深对象的副本,也就是说,它不只是复制容器还包括所有包含的对象(递归地,如果容器包含其他容器 - 比如说快三倍......; - )。
并非每个对象都可以被复制(深度或浅度) - 例如,无法复制打开的文件对象(如果您有这种奇怪的高级需求,则需要其他方法)。但是,对于一个字符串作为键和值的字典,我在答案开头提到的简单方法就足够了,而且速度也很快; - )。