A Function's name during its definition

Mark Bourne nntp.mbourne at spamgourmet.com
Tue Feb 7 18:04:54 EST 2023


Stefan Ram wrote:
> Mark Bourne <nntp.mbourne at spamgourmet.com> writes:
>> In the second case, eval() only gets the globals and immediate locals,
> 
>    Yes, I think you are right. Curiously, the following program would
>    mislead one to thing that eval /does/ see the intermediate names:
> 
>    main.py
> 
> def f():
>      x = 22
>      def g():
>          print( x )
>          print( eval( 'x' ))
>      g()
> f()
> 
>    output
> 
> 22
> 22
> 
>    . But "print( x )" had the effect of making that x local.
>    Without it, we see the error:
> 
>    main.py
> 
> def f():
>      x = 22
>      def g():
>          print( eval( 'x' ))
>      g()
> f()
> 
>    error output
> 
> NameError: name 'x' is not defined

That is interesting.  I know assigning to a value creates a local 
version (and the non-local then can't be accessed, even before the new 
value was assigned), but hadn't realised just referencing it brought it 
into local scope for reading.  I guess that's to do with closures, where 
any variables referenced within the function get bound to the function's 
scope.  e.g. if g() includes a reference to x [as it does in the first 
example above], and f() returned a reference to g(), calling g() later 
[from outside of f()] by using that reference would still be able to 
access x.

With just the eval() call and no other reference to x, the interpreter 
doesn't know at that time the closure is created that there is a 
reference to x.  At that point, the 'x' is just text in a string.  It's 
only when eval() gets called that it tries to execute that string as 
Python code - and finds that x isn't in scope.

I'm not all that familiar with the concept of closures, so may have got 
some of the terminology and details wrong - but it's something along 
those lines.  I'm sure others will correct me...

-- 
Mark.


More information about the Python-list mailing list