Программист на Python может узнать, какие именно переменные определенны в данный момент в интерпретаторе. Переменные можно разделить на локальные и глобальные. Глобальные определены на верхнем уровне кода снаружи функций и классов (грубо говоря без отступов слева). Локальные переменные наоборот определены внутри своих зон видимости, ограниченных классами и функциями.
Функция globals()
выдает словарь глобальных переменных (ключ – имя переменной). Функция locals()
возвращает словарь только локальных переменных. Пример:
x, y = 5, 10 def test(): y, z = 33, 44 print('globals:', globals()) print('locals:', locals()) test() """Вывод: globals: {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': ...>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/.../vars.py', '__cached__': None, 'x': 5, 'y': 10, 'test': <function test at 0x107677280>} locals: {'y': 33, 'z': 44}"""
Обратите внимание, что переменная y
в locals()
имеет другое значение, нежели чем в globals()
. Это две разные переменные из разных областей, но внутри функции приоритет имеет локальная y
.
Еще важно знать, что в список переменных входят не только простые переменные, которые вы определяете через знак присваивания, но и функции, классы и импортированные модули!
Через словари из locals()
и globals()
переменные можно не только читать, но и создавать, перезаписывать и удалять:
>>> x = 10 >>> globals()['x'] = 5 >>> x 5 >>> globals()['new_var'] = 10 >>> new_var 10 >>> del globals()['new_var'] >>> new_var Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'new_var' is not defined
vars()
vars()
ведет себя как locals()
, если вызвана без аргумента, а если с аргументом, то она просто получает __dict__
от аргумента. Если его нет у аргумента, то будет TypeError
.
class Foo: def __init__(self): self.x = 5 f = Foo() print(vars(f)) # {'x': 5} print(vars(f) == f.__dict__) # True
В глобальном контексте все три функции возвращают одно и тоже – глобальные переменные. Проверьте:
print(globals()) print(locals()) print(vars()) print(globals() == locals() == vars()) # True
dir()
Без параметров dir()
возвращает список имен переменных. В глобальном контексте – глобальных переменных, в локальном – список имен локальных переменных.
def test(): x = 10 print(dir()) # ['x'] y = 10 test() print(dir()) # ['__annotations__', ..., '__spec__', 'test', 'y']
Все рассмотренные выше функции являются встроенными и не требуют импортов.
P. S.
В отличие он некоторых других языков в Python блоки типа for, if, while, with
не создают областей видимости (scope) для переменных, то есть переменная внутри и снаружи блока будет одна и та же:
x = 1 if True: x = 2 print(x) # 2
Частая ошибка – затирание внешней переменной в цикле for:
i = 10 for i in range(5): # затирает i ... print(i) # 4
Зоны видимости отделяются только функциями, классами и модулями. Здесь все переменные x – разные:
x = 1 class Foo: x = 2 def method(self): x = 3 return x print(x, Foo.x, Foo().method()) # все 3 разные
Самая широкая зона видимости называется builtin. В нее попадают все имена, известные интерпретатору в данный момент, включая вещи импортированные из других модулей.
>>> from math import pi >>> pi, id(pi) (3.141592653589793, 4465320624) >>> pi = 3 >>> pi, id(pi) (3, 4462262880) >>> from math import pi >>> pi, id(pi) (3.141592653589793, 4465320624)
Казалось бы мы затерли pi, но мы затерли его лишь в глобальной области видимости. Повторно импортируя pi, мы получаем старую переменную с тем же адресом, иными словами мы достаем ее из builtin области в global.
Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈