TL;DR: I want a locals() that looks in a containing scope.
Hi, all.
I'm teaching a course on Python programming to some chemist friends, and I want to be sure I really understand scope.
Consider:
def a():
x = 1
def b():
print(locals())
print(globals())
b()
Locals prints an empty environment, and globals prints the usual globals. How do I get access to the environment where x is stored? Clearly the interpreter knows about it because I can refer to it.
Related: When does scoping happen? The following nameErrors on a = x+2 only if x=3 is included:
def a():
x = 1
def b():
a = x+2
x = 3
b()
If you comment out x=3, the code works. Does this mean that python makes a lexical-scope pass over the code before it interprets it?
Python locals() Function The locals() function returns the local symbol table as a dictionary. A symbol table contains necessary information about the current program.
globals() always returns the dictionary of the module namespace. locals() always returns a dictionary of the current namespace. vars() returns either a dictionary of the current namespace (if called with no argument) or the dictionary of the argument.
The LEGB rule is a kind of name lookup procedure, which determines the order in which Python looks up names. • For example, if we access a name, then Python will look that name up sequentially in the local, enclosing, global, and built-in scope. Local (or function) scope.
What is happening in your code is that when python see's the x=3
line in your b()
method, it is recreating x
with a scope within the b
function instead of using the x
with it's scope in the a
function.
because your code then goes:
a = x+2
x = 3
it is saying that you need to define the inner scoped x
before referencing it.
however, when you do not have the assigning of x
within the b
function python does not attempt to make a lower scoped x
and will not throw any errors.
The following code will illustrate this:
def a():
x = 1
def b():
x = 3
print (x)
def c():
print (x)
b()
c()
print (x)
a()
However if you were to declare x
as global
you could use it within a function, like so:
def a():
global x
x = 1
def d():
global x
x += 2
print (x)
d()
print (x)
a()
Python 3 has also added a nonlocal
keyword that will let you access a variable from an enclosing scope, usage is like:
def a():
x = 1
def d():
nonlocal x
x += 2
print (x)
d()
print (x)
a()
Will print the same results as the global
example.
In case I miss-read the question:
As per the answer to Get locals from calling namespace in Python:
you can use:
import inspect
def a():
x = 1
def d():
frame = inspect.currentframe()
try:
print (frame.f_back.f_locals)
finally:
del frame
d()
a()
to get the local scope of the functions caller.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With