Простое объяснение
globals()
относится к словарю атрибутов текущего модуля.locals()
относится к текущим локальным переменным в вашей функции / фрагменте кода.
Установка переменной будет только когда-либо изменяться locals()
.(Если вы не укажете python иначе, используя ключевое слово global
или nonlocal
.)
Здесь приведен пример
По умолчанию для глобалов области модуля по умолчаниюкак локальные:
>>> globals() is locals()
True
Поскольку глобальные переменные в данном случае являются локальными, изменение локальных также изменит глобальные переменные.
Если вы создадите функцию и посмотрите там на локальных, вы увидитечто местные значения будут отличаться
>>> def test():
... print("globals is locals:", globals() is locals())
... print("globals:", globals())
... print("locals:", locals())
>>> test()
globals is locals: False
globals: {'__name__': '__main__', ...}
locals: {}
Местные жители будут автоматически обновляться при изменении локальной функции-функции
>>> def test2():
... print("locals 1:", locals())
... x = 1
... print("locals 2:", locals())
>>> test2()
locals 1: {}
locals 2: {'x': 1}
Нечто подобное происходит при создании новых классов
>>> class Test:
... print("locals:", locals())
locals: {'__module__': '__main__', '__qualname__': 'Test'}
Более подробное объяснение
Если вы хотите узнать, почему глобалы и местные жители таковы, как они есть, давайте посмотрим, что происходит под капотом Python.
Некоторая земляработа
Весь код Python передает то, что в какой-то момент соответствует функции eval
или exec
.Эти функции принимают три параметра: source
, globals
(по умолчанию - текущие глобальные) и locals
(по умолчанию - текущие локальные).
Функция globals()
и locals()
вернет все, что былопередается в функции eval
или exec
, показанные выше.
Что делает оболочка Python?
Если вы делаете
>>> print(globals())
REPL будет внутренне делать что-то вроде
# 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())")
Как вы можете видеть, оболочка Python в какой-то момент установит globals
и locals
в один и тот же диктофон.
Выполнение функции
Внутренне выполнение функции по существу будет выполнять три вещи:
- Анализировать аргументы, переданные функции, и добавлять их в локальные переменные.
- Выполнить код функции
- Вернуть ее результат.
Здесь псевдоалгоритм:
def __call__(*args, **kwargs):
local_variables = parse_signature_with_args(args, kwargs)
exec(function_source, function_globals, local_variables)
return function_result
Создание новогоклассы
При использовании оператора класса весь код с отступом будет выполняться отдельно.
- создан новый словарь, который будет действовать как
locals()
- Ваш код выполняется с указанными локальными элементами.
- Класс создается с передачей локальных элементов в
Если вы выполните этот код:
class Test:
a = 5
Это примерно то, что происходит:
# 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)
Как это сопоставляется с импортом модуля
Если вы импортируете модуль, запустится сложный механизм импорта.Это упрощенный обзор:
- Интерпретатор будет искать, если модуль уже был импортирован.
- Интерпретатор найдет файл.
- Тогда файлчтение и анализ
- Создан объект модуля.
- Сценарий python выполняется, и его глобальные и локальные значения будут установлены на атрибут
__dict__
новых модулей. - Возвращается объект модуля.
Он работает примерно так:
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