Python3 globals() and locals() contents

samtal

In my Python3 learning, while trying out globals() and locals(), I made a very basic, stand-alone Python program and received results for which I ask for expert explanation.

I then executed the same 2 functions inside my Python program (any) and received a list of many (all ?) values in my program, regardless if it was declared local or global or non.

My understanding was that the globals() functions holds a list of all values that were declared as globals (same for locals), but according to my observation, the results show something different.

Can anyone explain what I see and why?

Here is the program and the results:

The python program:

 print("Globals=",globals())
 print("Locals=",locals())

The result (for the above 2-lines program):

=============== RESTART: /home/pi/Junk/globals_locals_test.py ==========
Globals= {'__package__': None, '__spec__': None, '__loader__': <class '
_frozen_importlib.BuiltinImporter'>, '__doc__': None, '__file__': '
/home/pi/Junk/globals_locals_test.py', '__builtins__': <module 'builtins'
 (built-in)>, '__name__': '__main__'}
Locals= {'__package__': None, '__spec__': None, '__loader__': <class '
_frozen_importlib.BuiltinImporter'>, '__doc__': None, '__file__': '
/home/pi/Junk/globals_locals_test.py', '__builtins__': <module 'builtins'
 (built-in)>, '__name__': '__main__'}
>>>
StuxCrystal

Simple explanation

globals() refers to the current modules' attribute dictionary. locals() refers to the current local variables in your function/code-snippet.

Setting a variable will only ever change locals(). (Unless you tell python otherwise using the global or nonlocal keyword.)

Here an example

By default on module-scope globals is the same dict as locals:

>>> globals() is locals()
True

Since globals is locals in this case, modifying the locals will also modify the globals.

If you create a function and look at locals in there, you will see that locals will differ

>>> def test():
...    print("globals is locals:", globals() is locals())
...    print("globals:", globals())
...    print("locals:", locals())
>>> test()
globals is locals: False
globals: {'__name__': '__main__', ...}
locals: {}

Locals will automatically update when you change a function-local variable

>>> def test2():
...     print("locals 1:", locals())
...     x = 1
...     print("locals 2:", locals())
>>> test2()
locals 1: {}
locals 2: {'x': 1}

Something similar happens when creating new classes

>>> class Test:
...     print("locals:", locals())
locals: {'__module__': '__main__', '__qualname__': 'Test'}

More in-depth explanation

If you want to know why globals and locals are the way they are let's look at what happens under the hood of Python.

Some ground work

All python code passes what equates to the eval or exec function at some point. These functions accept three parameters: source, globals (defaults to current globals) and locals (defaults to current locals).

The function globals() and locals() will return whatever has been passed into the eval or exec functions shown above.

What does the Python Shell do?

If you do

>>> print(globals())

The REPL will internally do something along the lines of

# This variable stores your globals.
_my_main_module = {}

def exec_some_line(line):
    return eval(line, globals=_my_main_module, locals=_my_main_module)

# ...

exec_some_line("print(globals())")

As you can see, the Python Shell will at some point set globals and locals to the same dict.

Function execution

Internally, function execution will essentially do three things:

  1. Parse the arguments passed to the function and add them to the local variables.
  2. Execute the code of the function
  3. Return its result.

Here a pseudo-algorithm:

def __call__(*args, **kwargs):
    local_variables = parse_signature_with_args(args, kwargs)
    exec(function_source, function_globals, local_variables)
    return function_result

Creating new classes

When using the class-statement, all indented code will be executed separately.

  1. a new dictionary is created that will act as locals()
  2. Your code is executed with said locals.
  3. The class is created passing locals in

If you execute this code:

class Test:
   a = 5

This is approximately what happens:

 # 1. A new dictionary is created
 _dict = type.__prepare__()
 _dict["__module__"] = __name__
 _dict["__qualname__"] = "Test"

 # 2. Execute the code
 exec("a = 5", globals=globals(), locals=_dict)

 # 3. A class is created
 Test = type("Test", (), _dict)

How this maps to module imports

If you import a module an intricate import mechanism starts. This is a simplified overview:

  1. The interpreter will look if the module has already been imported.
  2. The interpreter will find the file.
  3. Then the file is read and parsed
  4. A module object is created.
  5. The python script is executed and its globals and locals will be set to the new modules' __dict__ attribute.
  6. The module object is returned.

It works something like this:

import sys
from types import ModuleType
def __import__(name):
    # 1. See if module is already imported
    if name in sys.modules:
       return sys.modules[name]

    # 2. Find file.
    filename = find_out_path_to_file(name)

    # 3. Read and parse file
    with open(filename) as f:
      script = f.read()

    # 4. Create the new module
    module = ModuleType(name)

    # 5. Execute the code of the module.
    exec(script, globals=module.__dict__, locals=module.__dict__)

    # 6. Return the new module.
    return module

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Globals and Locals

locals() and globals() in stack trace on exception (Python)

difference between locals() and globals() and dir() in python

python quits unexpectedly when using locals() or globals()

locals() vs globals() in function

globals(), locals(), vars() do not work as expected in a function of python

scope of globals, locals, use with exec()

Does F# have a language construct to access the lexical scope (like python locals()/globals())

Python - How to obtain a dictionary(or even a list) of variables in a specific scope; more specific than locals/globals()

eval globals and locals argument do not work as expected

about pandasql locals() and globals() method issue

What's the difference between globals(), locals(), and vars()?

How to execute a callable in a given context (locals and globals)?

Destruction order between globals and static function locals

Is it possible to get locals() and globals() from an upper stack frame?

Using a list comprehension to look up variables works with globals() but not locals(). Why?

Is there are any way make locals() and globals() defaultdict-like

C++ - Different concurrent behavious when using locals and globals

View contents of QStandardItemModel in Locals View in Qt Creator

What happened when invoking locals() in python3?

Why is globals() a function in Python?

Reason for globals() in Python?

Python globals and keyword arguments

Globals between files in python

Python: Strange behavior of locals()

locals() and object reference in python

In Python, import a function using globals()

Python, Inject code into module globals

Sharing python globals() cross files