Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary creation with fromkeys and mutable objects. A surprise [duplicate]

Tags:

python

I came across this behavior that surprised me in Python 2.6 and 3.2:

>>> xs = dict.fromkeys(range(2), [])
>>> xs
{0: [], 1: []}
>>> xs[0].append(1)
>>> xs
{0: [1], 1: [1]}

However, dict comprehensions in 3.2 show a more polite demeanor:

>>> xs = {i:[] for i in range(2)}
>>> xs
{0: [], 1: []}
>>> xs[0].append(1)
>>> xs
{0: [1], 1: []}
>>> 

Why does fromkeys behave like that?

like image 838
joaquin Avatar asked Nov 17 '11 21:11

joaquin


1 Answers

Your Python 2.6 example is equivalent to the following, which may help to clarify:

>>> a = []
>>> xs = dict.fromkeys(range(2), a)

Each entry in the resulting dictionary will have a reference to the same object. The effects of mutating that object will be visible through every dict entry, as you've seen, because it's one object.

>>> xs[0] is a and xs[1] is a
True

Use a dict comprehension, or if you're stuck on Python 2.6 or older and you don't have dictionary comprehensions, you can get the dict comprehension behavior by using dict() with a generator expression:

xs = dict((i, []) for i in range(2))
like image 128
Andrew Clark Avatar answered Oct 01 '22 13:10

Andrew Clark