brett
brett

Reputation: 7

Trying to create new dictionaries through iteration

I'm not even able to properly search google for it, but here goes:

a = {}
b = {}
c = [a, b]
for d in c:
    d['ID'] = d
print c

returns:

[{'ID': {...}}, {'ID': {...}}]

why isn't it:

[{'ID': a}, {'ID': b}]

Upvotes: 0

Views: 118

Answers (4)

mattbasta
mattbasta

Reputation: 13709

for d in c:
    d['ID'] = d

should be

c = [{'ID': d} for d in c]

Your code is adding the ID element to each of the dicts in c. That means a = {'ID': a} after your code has run. It contains a reference to itself.

My snippet generates a new dict with a property 'ID' containing a value from c.

Upvotes: 0

TheoretiCAL
TheoretiCAL

Reputation: 20571

Consider what the loop is doing: a = {} b = {} c = [a, b]

    for d in c:
        d['ID'] = d

d will be either a or b, such that

    a['ID'] = a
    b['ID'] = b

but recall a and b are {}, the dics themselves. as a result, your assigning ['ID'] to the dic itself, creating a loop. When you

print(c)

you get [{'ID': {...}}, {'ID': {...}}] because the value of the key is the dic itself and not the variable representation of it, hence you get {...} to reflect the nature of the loop. Note how after this a['ID']['ID'], or even a ['ID']['ID']['ID']['ID'] is {'ID': {...}}, because the value of the key is the dic itself, not the variable pointing to it.

Upvotes: 0

abarnert
abarnert

Reputation: 365767

Let's step through this:

a = {}
b = {}
c = [a, b]

So far, so good.

for d in c:
    d['ID'] = d

We can unroll this to:

d = c[0]
d['ID'] = d
d = c[1]
d['ID'] = 1

And expand that to:

d = a
d['ID'] = d
d = b
d['ID'] = d

Now substitute:

a['ID'] = a
b['ID'] = a

So, let's forget about the loop for a second and look at what that does:

>>> a = {}
>>> a['ID'] = a
>>> a
{'ID': {...}}

In other words, you're making each dict recursively contain a copy of itself, under the key ID. How would you expect this to be printed?

So, the obvious thing to do is to try to print the whole dictionary:

{'ID': {'ID': {'ID': { …

But this would be an infinitely-long string, and Python would run out of stack space before reaching infinity. So it needs to truncate it somehow.

It can't print this:

{'ID': a}

Because a is just a name that happens to be bound to the dict, just like d is at the time. In fact, the loop doesn't even know that a is bound to that at the time; it knows that d is. But even if it did know, the result would be wrong. Think about this:

>>> e = a
>>> a = 0
>>> e
???

So, the obvious answer is to use an ellipsis (kind of like I did in the human-readable version) to represent "and so on".

Upvotes: 2

Anton Kovalenko
Anton Kovalenko

Reputation: 21507

a is a dictionary.

b is a dictionary.

c is a list of two dictionaries (not "two names" or "two variables").

Another socratic explanation: If it would return [{'ID': a}, {'ID': b}], values displayed as a and b would be of which type?

Upvotes: 0

Related Questions