tags:

views:

213

answers:

4

I would expect that the following code would just initialise the dict_a, dict_b and dict_c dictionaries. But it seams to have a copy through effect:

dict_a = dict_b = dict_c = {}
dict_c['hello'] = 'goodbye'

print dict_a
print dict_b
print dict_c

As you can see the result is as follows:

{'hello': 'goodbye'}
{'hello': 'goodbye'}
{'hello': 'goodbye'}

Why does that program give the previous result, When I would expect it to return:

{}
{}
{'hello': 'goodbye'}
+4  A: 

This is because in Python, objects are just references. When you assign dict_a = dict_b, you are really copying a memory address (or pointer, if you will) from dict_b to dict_a. There is still one instance of a dictionary.

To get the desired behavior, use the dict.copy() method.

>>> a = {1:2}
>>> b = a.copy()
>>> b
{1: 2}
>>> b[3] = 4
>>> a
{1: 2}
>>> b
{1: 2, 3: 4}
>>> 
danben
So dictionaries are objects, would this still be the case with say an integer variable or would the type of a variable have no impact on it being an object?
Marcus Whybrow
Integers are immutable so I'm not sure how you would intend to reproduce this behavior. In any case, literal values for some types are interned (ie there is only one instance of each). You can verify that two integer variables containing the same value actually point to the same instance of the integer via the `id()` function.
danben
In any case, everything in Python is an object. To see the functions that belong to the integer object 1, you can execute `dir(1)`.
danben
Everything is an object, and variables are names that we assign to objects (not the other way around!) So if you do `a = b = c = 1; a +=1`, then everything gets assigned to the object `1`, and then `a` gets assigned to the object `2`. With mutable objects like lists, dicts and sets, you can change the object itself, which will be seen by all names assigned to that object, but with ints, strings, tuples, and other immutable objects, all you can do is assign the name to a different object.
jcdyer
Ah I see, that makes perfect sense.
Marcus Whybrow
*"objects are just references"* This is not true. Objects are objects. Names reference them.
Mike Graham
Not as worded no, but I know what @danben meant, thanks for clearing up any confusion though.
Marcus Whybrow
A: 

Your first assignment assigns the same dictionary object to the variables dict_a, dict_b, and dict_c. It is equivalent to dict_c = {}; dict_b = dict_c; dict_a = dict_c.

msalib
+1  A: 

As danben previously said, you're just copying the same dict into 3 variables, so that each one reffers to the same object.

To get the behaviour you want, you should instanciate a different dict in each variable:

>>> dict_a, dict_b, dict_c = {}, {}, {}
>>> dict_c['hello'] = 'goodbye'
>>> print dict_a
{}
>>> print dict_b
{}
>>> print dict_c
{'hello': 'goodbye'}
>>>
MatToufoutu
Thanks, this was what I was intending to do when I stumbled upon this subject. Although its not an answer to the question, thanks very much.
Marcus Whybrow
+2  A: 

Even though

>>> dict_a, dict_b, dict_c = {}, {}, {}

is the right way to go in most cases, when it get more than 3 it looks weird

Imagine

>>> a, b, c, d, e, f = {}, {}, {}, {}, {}, {}

In cases where I wanna initialize more than 3 things, I use

>>> a, b, c, d, e, f, = [dict() for x in range(6)]

Caution: Do not use [{} for x in range(6)]

jeffjose