Argument arguments not available in dictation

Why can't I access function arguments with eval in dict's understanding?

 ARGS1 = ('a1', 'b1') def foo1(a1, b1): return {arg:eval(arg) for arg in ARGS1} print foo1("A1", "B1") # NameError: name 'a1' is not defined 

The same in understanding the list is fine:

 ARGS2 = ('a2', 'b2') def foo2(a2, b2): return [eval(arg) for arg in ARGS2] print foo2("A2", "B2") # OK, print: ['A2', 'B2'] 

It also works well without a function:

 ARGS3 = ('a3', 'b3') a3, b3 = ("A3", "B3") print {arg:eval(arg) for arg in ARGS3} # OK, print: ['A3', 'B3'] 

Or, if global values ​​are defined:

 ARGS4 = ('a4', 'b4') a4, b4 = ("A4", "B4") def foo4(): return [eval(arg) for arg in ARGS4] print foo4() # OK, print: ['A4', 'B4'] 

It really seems like a mistake, but maybe I missed something.

(EDITED includes examples without function and with globals)

+4
source share
1 answer

In a new scope, as a function, markup is performed.

Thus, the locales of an expression are limited only by the names specified in the loop, in this case arg . Local parent functions are not taken into account, since closures are only associated at compile time. Names referenced by eval() cannot use closure.

The following does not work either:

 >>> ARGS = ('a', 'b') >>> def bar(a, b): ... def foo(): ... for arg in ARGS: ... eval(arg) ... return foo ... >>> print bar("A", "B")() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in foo File "<string>", line 1, in <module> NameError: name 'a' is not defined 

The names a and b not available to the internal function foo unless the compiler has determined that this function really needs access to them:

 >>> def bar2(a, b): ... def foo(): ... a, b ... for arg in ARGS: ... eval(arg) ... return foo ... >>> print bar2("A", "B")() None >>> print bar2("A", "B").func_closure (<cell at 0x1051bac20: str object at 0x104613328>, <cell at 0x1051bacc8: str object at 0x1045971e8>) >>> print bar2("A", "B").__code__.co_freevars ('a', 'b') 

Here, the string a, b can refer only to the parent scopes (they are not assigned by foo() themselves), so the compiler created a closure for them, and the names became available as local within foo() .

List conventions in Python 2 do not have their own namespace, a missed fix in Python 3 and not extended to dict and sets understanding. See Python list rename names even after understanding. Is it correct?

+5
source

Source: https://habr.com/ru/post/1500991/


All Articles