Shi Yan
Shi Yan

Reputation: 95

Unexpected result when generating a list of dicts

I would like to generate a list of dicts by two layer loop. At the outer loop, the generated dict will be appended into the list. But the output is not expected as below:

inf = []
infdic = {}
keys = ['t1', 't2', 't3', 't4', 't5']

for c1 in range(2):
    for c2 in range(5):
        value = c1*10+c2
        key = keys[c2]
        infdic[key] = value
    inf.append(infdic)
    print c1, inf

The result of above code is:

0 [{'t4': 3, 't5': 4, 't2': 1, 't3': 2, 't1': 0}]
1 [{'t4': 13, 't5': 14, 't2': 11, 't3': 12, 't1': 10}, {'t4': 13, 't5': 14, 't2': 11, 't3': 12, 't1': 10}]

But what I want should be:

0 [{'t4': 3, 't5': 4, 't2': 1, 't3': 2, 't1': 0}]
1 [{'t4': 3, 't5': 4, 't2': 1, 't3': 2, 't1': 0}, {'t4': 13, 't5': 14, 't2': 11, 't3': 12, 't1': 10}]

It looks like the list inf is pointed to infdic, and it always changes as it does. I am a little confused about how could this happen and how to fix it.

Upvotes: 0

Views: 108

Answers (2)

Newb
Newb

Reputation: 2930

The problem is that you're not resetting infdic in your outermost loop.

You loop through c1 and you set up infdic as expected. But then you loop through c2 and overwrite the contents of infidc! It can be fixed by setting infdic = {} in your outermost loop:

inf = []
keys = ['t1', 't2', 't3', 't4', 't5']

for c1 in range(2):
    infdic = {}
    for c2 in range(5):
        value = c1*10+c2
        key = keys[c2]
        infdic[key] = value
    inf.append(infdic)
    print c1, inf

Also, regarding your observation:

It looks list "inf" is pointed to "infdic", and it always changes as it does.

Yes, that's right. When you write inf.append(infdic) you are appending a pointer to infdic to the list inf. You're not copying a static version of the list (though you could using copy.deepcopy). I suggest you read up on how Python uses pointers, and shallow/deep copying.

Upvotes: 1

Alex Martelli
Alex Martelli

Reputation: 881575

It looks list "inf" is pointed to "infdic", and it always changes as it does.

Yep, that's exactly what your code says to do, and, lo and behold, Python does precisely what you tell it to!-)

Fix: make a new infdic each time around:

for c1 in range(2):
    infdic = {}
    for c2 in range(5):
        ...

Upvotes: 2

Related Questions