[issue43605] Eval/exec and comprehension scopes unclear in documentation
Cong Ma firstname.lastname@example.org added the comment:
Some more context: Issue 37646. The demo in that one was "eval inside list-comprehension-scope", while this one is the other way around.
Perhaps another example may better illustrate the interplay between eval and the execution environment:
``` def f(): x = 1 def g(): return eval("x") return g enc = f() enc() ```
We get ``NameError: name 'x' is not defined``.
The reason is that, during compilation the compiler doesn't and cannot care about what the string "x" means as an argument to eval(). To the compiler it's just a string constant passed to a function, and it's not much different from ``` return print("x") ``` The compiler decides that the enclosed function g() has no locals in its block. And since there's no global with the name ``x`` either, when the dynamic expression is evaluated in eval() in that environment, the name doesn't resolve, because "eval() doesn't have access to the enclosing scope".
But the following is different:
``` def f(): x = 1 def g(): x # <----- return eval("x") return g enc = f() enc() # return value: 1 ```
The marked line introduces name ``x`` as a local by virtue of merely having it in an expression-statement. Inside the function block of g(), we can imagine that the name resolution "goes up one level" into the enclosing block of f() where it is bound to the int object. When eval() is called there, the name does resolve.
I'm trying to think up a mental model but I'm afraid I can't find a simple one, except "once compiled, it's compiled, and eval() must learn to work with the already-compiled code". A much more in-depth description of name binding and execution in CPython is given here:
especially in the section "``LOAD_DEREF`` and ``STORE_DEREF``".
_______________________________________ Python tracker email@example.com https://bugs.python.org/issue43605 _______________________________________