Using A List Comprehension To Look Up Variables Works With Globals() But Not Locals(). Why?
Solution 1:
If we dissemble a more basic list-comprehension. we can see why this is happening:
>>> import dis
>>> dis.dis("[i for i in range(10)]")
10 LOAD_CONST 0 (<code object <listcomp>)
3 LOAD_CONST 1 ('<listcomp>')
6 MAKE_FUNCTION 09 LOAD_NAME 0 (range)
12 LOAD_CONST 2 (10)
15 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
18 GET_ITER
19 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
22 RETURN_VALUE
So, on line 9
, we see that a list-comp actually makes a function which is called (you may be more used to this when using generators). Therefore, the function would have its own set of local variables as it is in a separate scope - thus yielding this unexpected behaviour.
Furthermore, as pointed out by @juanpa
, the "What's New in Python3" docs do explicitly state the following:
list comprehensions have different semantics: they are closer to syntactic sugar for a generator expression inside a
list()
constructor, and in particular the loop control variables are no longer leaked into the surrounding scope.
Note also that there is a bug page on this: https://bugs.python.org/issue21161, however juanpa has convinced me that this isn't a bug for the reason that it is clearly documented to work this way!
Solution 2:
List comprehensions define a new scope in Python 3, which they did not do in Python 2. Simply put, A
, B
, and C
aren't local variables in the list comprehension in Python 2.
As an aside, you probably should have been using an explicit dict {'A': 1, 'B': 2, 'C': 3}
instead of separate variables all along. Now is a good time to fix that.
Post a Comment for "Using A List Comprehension To Look Up Variables Works With Globals() But Not Locals(). Why?"