2010-08-14 68 views
2
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 

这第一次因为某些原因后,输出真。 tokens_raw_oldtokens_raw具有相同的数据,即使单独修改了tokens_raw也是如此。我在某个地方犯了一个愚蠢的错误,还是问题出在第二个while循环内(这又是一次引用tokens_raw_old)?如果没有明显的错误,我会发布更多的代码。为什么这个变量被改变了?

回答

7

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) 

这可以说是相当缓慢的,但是,“当你需要它,你需要它” - 它使物体的副本,也就是说,它不只是复制容器也全部包含的对象(递归,如果容器包含其它容器 - 说三次快速...;-)。

并不是每一个对象都可以被复制(深或浅) - 例如,一个打开的文件对象无法复制(你需要其他的方法,如果你有这样的怪异,高级需求)。但是,对于一个字符串作为键和值的字典,我在这个答案开始时提到的简单方法就足够了,而且速度也很快;-)。

+0

我实际上在我粘贴的代码中犯了一个错误; tokens_raw是一个列表,而不是一个字典,所以.copy()不是一个有效的方法。然而,这个回应仍然是有道理的,我发现使用'tokens_raw_old = tokens_raw [:]'具有和你所建议的相同的效果。谢谢您的帮助。 :) – Fraxtil 2010-08-14 03:20:23

+1

@Fraxtil,肯定的,但我个人厌恶日益流行的'somelist [:]'成语 - '名单(somelist)'就是** **这样的方式来更可读浅复制清单(或者就此而言,制作任何输入序列的列表版本)。啊,风格问题,我想! - ) – 2010-08-14 03:22:30