190

What is the difference between globals(), locals(), and vars()? What do they return? Are updates to the results useful?

Ethan Furman
  • 63,992
  • 20
  • 159
  • 237

1 Answers1

221

Each of these return a dictionary:

  • 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.

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 prints 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:

  1. This behavior is CPython specific -- other Pythons may allow the updates to make it back to the local namespace automatically.
  2. In CPython 2.x it is possible to make this work by putting an 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.

user2357112
  • 260,549
  • 28
  • 431
  • 505
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
  • 4
    The part "and any assignments to the dictionary are not reflected in the actual local namespace" might be worded [a bit to definite](http://ideone.com/7RtOi). – Sven Marnach Nov 01 '11 at 17:18
  • Oddly enough, you can access variables added to to a `vars()` or `locals()` dictionary called within a function if you use `eval()`. EG: `def test(): huh = locals(); huh['d'] = 4; print eval('d')` prints 4 when `test()` is executed! – Mark Mikofski Aug 07 '13 at 17:37
  • 1
    Actually assignment to the `dict` (returned by `locals()`) happens to be reflected in the local namespace and changes to the local namespace happens to be reflected in the `dict` (in my python). The only thing is that the specification does not guarantee this behaviour. – skyking Jul 22 '15 at 11:02
  • 1
    Term *name scope* usage looks more easy for me than *namespace*. – overexchange May 04 '17 at 21:53
  • `vars` is coming from `__builtins__` module without importing that module(magic). Where is `locals` & `globals` coming from? – overexchange May 04 '17 at 21:56
  • @overexchange: *namespace* is the Python term; `locals` and `globals` are also in `__builtins__`. – Ethan Furman May 04 '17 at 22:03
  • 1
    @overexchange: `import this` and in google `site:docs.python.org namespace` – Ethan Furman May 04 '17 at 22:13
  • can one update any of these in python 3 and have the script actually work? – Charlie Parker Oct 16 '17 at 23:08
  • @CharlieParker: You'll need to ask that as it's own question. The answer is both yes and no, depending on exactly what your script is trying to do. – Ethan Furman Oct 16 '17 at 23:40
  • Is there a scenario where you need to use any of these? I never used any of them so I wonder in what situation would you have no way around using them? – Calvin Ku Jul 26 '18 at 02:34
  • @CalvinKu : Well, depends on what you mean "no way around those" - in Python, there are always more ways, how to achieve something. However, as an example - right now I'm writing evaluation script of student code's and I need to make sure, they don't change local variables during their run. The best way is to get a copy of variables before their call, get a copy of variables after the call and compare them. – Otaj Oct 25 '18 at 12:16
  • Could you speak a bit about the module namespace? Thanks – Brendan Metcalfe Aug 19 '19 at 01:51
  • @EthanFurman How does one access f_locals attribute of a particular frame object directly? – astralwolf Sep 19 '21 at 21:54