4
>>> a = 1
>>> print { key: locals()[key] for key in ["a"] }
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <dictcomp>
KeyError: 'a'

How can I create a dictionary with a comprehension like this?

It should result in {"a": 1}.

bad_coder
  • 11,289
  • 20
  • 44
  • 72
J V
  • 11,402
  • 10
  • 52
  • 72

2 Answers2

12

A dict comprehension has its own namespace, and locals() in that namespace has no a. Technically speaking, everything but the initial iterable for the outermost iterable (here ["a"]) is run almost as a nested function with the outermost iterable passed in as an argument.

Your code works if you used globals() instead, or created a reference to the locals() dictionary outside of the dict comprehension:

l = locals()
print { key: l[key] for key in ["a"] }

Demo:

>>> a = 1
>>> l = locals()
>>> { key: l[key] for key in ["a"] }
{'a': 1}
>>> { key: globals()[key] for key in ["a"] }
{'a': 1}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • why in the world to dict comprehensions have their own namespace? – abcd Apr 09 '15 at 20:09
  • 1
    @dbliss: because generator expressions do. And list comprehensions after Python 2.7. And set comprehensions. It makes the implementation cleaner and keeps the names local (so they don't leak to the surrounding scope). – Martijn Pieters Apr 09 '15 at 20:35
2

You can try using globals() instead:

print {key : globals()[key] for key in ["a"]}

since a is not defined in the scope of the dict comprehension (as @MartijnPieters said).

Christian Tapia
  • 33,620
  • 7
  • 56
  • 73