views:

47

answers:

1
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

This outputs True after the first time for some reason. tokens_raw_old has the same data as tokens_raw, even after tokens_raw alone was modified. Did I make a dumb mistake somewhere, or does the problem lie within the second while loop (which, again, never once references tokens_raw_old)? If there are no obvious mistakes, I'll post more code.

+7  A: 

tokens_raw_old = tokens_raw means: make a new reference called token_raw_old to the same object to which name tokens_raw refers at this time. It's the same object, not a copy of the object! So, changes to this one and only object made through one of the references obviously also affect the very same object when examined through the other reference.

If you want a copy, ask for a copy! For example, since tokens_raw is a dict with immutable values (and keys, but that's frequent in dicts):

tokens_raw_old = tokens_raw.copy()

will be sufficient. Identically (just a style issue), so will

tokens_raw_old = dict(tokens_raw)

(make a copy by "calling the type as a copy constructor", a concept that appeals to C++ programmers -- of which I'm one, so I really like this form;-).

If you need to cover for a general case (tokens_raw being of many possible different types, or values within it being perhaps modified):

import copy

tokens_raw_old = copy.deepcopy(tokens_raw)

This can be quite slow, but, "when you need it, you need it" -- it makes a deep copy of the object, that is, it doesn't just copy the container but also all contained objects (recursively, if a container contains other containers -- say that three times fast...;-).

Not every object can be copied (deeply or shallowly) -- for example, an open file object cannot be copied (you need other approaches if you ever have such weird, advanced needs). But, for a dict with strings as keys and values, the simple approaches I mentioned at the start of this answer will suffice, and be quite speedy too;-).

Alex Martelli
I actually made a mistake in the code I pasted; tokens_raw is a list, not a dict, so .copy() isn't a valid method. However, the response still makes sense, and I've found that using `tokens_raw_old = tokens_raw[:]` has the same effect as what you suggested. Thanks for the help. :)
Fraxtil
@Fraxtil, sure, but I personally loathe the ever-popular `somelist[:]` idiom -- `list(somelist)` is just **so** much more readable as a way to shallow-copy a list (or, make a list version of any input sequence, for that matter). Ah well, matter of style, I guess!-)
Alex Martelli