What is the difference between globals()
, locals()
, and vars()
? What do they return? Are updates to the results useful?
globals() and locals() Method in Python. The built-in functions globals() and locals() returns the global and local symbols table respectively. Python interpreter maintains a data structure containing information about each identifier appearing in the program's source code.
A global variable is a variable that is accessible globally. A local variable is one that is only accessible to the current scope, such as temporary variables used in a single function definition.
Python locals() Function The locals() function returns the local symbol table as a dictionary. A symbol table contains necessary information about the current program.
Python globals() function is a built-in function used to update and return a dictionary of the current global symbol table. The functions and variables that are not associated with any class or function are stored globally. It is mostly used for debugging purposes to see what objects the global scope actually contains.
Each of these return a dictionary:
globals()
always returns the dictionary of the module namespacelocals()
always returns a dictionary of the current namespacevars()
returns either a dictionary of the current namespace (if called with no argument) or the dictionary of the argument.locals
and vars
could use some more explanation. If locals()
is called inside a function, it updates a dict with the values of the current local variable namespace (plus any closure variables) as of that moment and returns it. Multiple calls to locals()
in the same stack frame return the same dict each time - it's attached to the stack frame object as its f_locals
attribute. The dict's contents are updated on each locals()
call and each f_locals
attribute access, but only on such calls or attribute accesses. It does not automatically update when variables are assigned, and assigning entries in the dict will not assign the corresponding local variables:
import inspect def f(): x = 1 l = locals() print(l) locals() print(l) x = 2 print(x, l['x']) l['x'] = 3 print(x, l['x']) inspect.currentframe().f_locals print(x, l['x']) f()
gives us:
{'x': 1} {'x': 1, 'l': {...}} 2 1 2 3 2 2
The first print(l)
only shows an 'x'
entry, because the assignment to l
happens after the locals()
call. The second print(l)
, after calling locals()
again, shows an l
entry, even though we didn't save the return value. The third and fourth print
s show that assigning variables doesn't update l
and vice versa, but after we access f_locals
, local variables are copied into locals()
again.
Two notes:
exec "pass"
line in the function. This switches the function to an older, slower execution mode that uses the locals()
dict as the canonical representation of local variables.If locals()
is called outside a function it returns the actual dictionary that is the current namespace. Further changes to the namespace are reflected in the dictionary, and changes to the dictionary are reflected in the namespace:
class Test(object): a = 'one' b = 'two' huh = locals() c = 'three' huh['d'] = 'four' print huh
gives us:
{ 'a': 'one', 'b': 'two', 'c': 'three', 'd': 'four', 'huh': {...}, '__module__': '__main__', }
So far, everything I've said about locals()
is also true for vars()
... here's the difference: vars()
accepts a single object as its argument, and if you give it an object it returns the __dict__
of that object. For a typical object, its __dict__
is where most of its attribute data is stored. This includes class variables and module globals:
class Test(object): a = 'one' b = 'two' def frobber(self): print self.c t = Test() huh = vars(t) huh['c'] = 'three' t.frobber()
which gives us:
three
Note that a function's __dict__
is its attribute namespace, not local variables. It wouldn't make sense for a function's __dict__
to store local variables, since recursion and multithreading mean there can be multiple calls to a function at the same time, each with their own locals:
def f(outer): if outer: f(False) print('Outer call locals:', locals()) print('f.__dict__:', f.__dict__) else: print('Inner call locals:', locals()) print('f.__dict__:', f.__dict__) f.x = 3 f(True)
which gives us:
Inner call locals: {'outer': False} f.__dict__: {'x': 3} Outer call locals: {'outer': True} f.__dict__: {'x': 3}
Here, f
calls itself recursively, so the inner and outer calls overlap. Each one sees its own local variables when it calls locals()
, but both calls see the same f.__dict__
, and f.__dict__
doesn't have any local variables in it.
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