Перейти к содержимому

python 3 глобальные переменные. globals, locals, vars, dir – инспектируем переменные.

Программист на 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.

———————————————————————————————————————————

Руководство по глобальным переменным

16.02.2021

Переменная, доступ к которой можно получить из любого места в коде, называется глобальной. Ее можно определить вне блока. Другими словами, глобальная переменная, объявленная вне функции, будет доступна внутри нее.

С другой стороны, переменная, объявленная внутри определенного блока кода, будет видна только внутри этого же блока — она называется локальной.

Разберемся с этими понятиями на примере.

Пример локальных и глобальных переменных

def sum():  
    a = 10   # локальные переменные 
    b = 20  
    c = a + b  
    print("Сумма:", c)  
  
sum() 

Вывод: 

Сумма: 30.

Переменная объявлена внутри функции и может использоваться только в ней. Получить доступ к этой локальной функции в других нельзя.

Для решения этой проблемы используются глобальные переменные.

Теперь взгляните на этот пример с глобальными переменными:

a = 20  # определены вне функции
b = 10  


def sum():  
    c = a + b  # Использование глобальных переменных  
    print("Сумма:", c)  

  
def sub():  
    d = a - b  # Использование глобальных переменных 
    print("Разница:", d)  
  
  
sum()
sub()

Вывод:

Сумма: 30
Разница: 10

В этом коде были объявлены две глобальные переменные: a и b. Они используются внутри функций sum() и sub(). Обе возвращают результат при вызове.

Если определить локальную переменную с тем же именем, то приоритет будет у нее. Посмотрите, как в функции msg это реализовано.

def msg():  
    m = "Привет, как дела?"  
    print(m)  
  
msg()  
m = "Отлично!"  # глобальная переменная
print(m) 

Вывод:

Привет, как дела?
Отлично!

Здесь была объявлена локальная переменная с таким же именем, как и у глобальной. Сперва выводится значение локальной, а после этого — глобальной.

Ключевое слово global

Python предлагает ключевое слово global, которое используется для изменения значения глобальной переменной в функции. Оно нужно для изменения значения. Вот некоторые правила по работе с глобальными переменными.

Правила использования global

  • Если значение определено на выходе функции, то оно автоматически станет глобальной переменной.
  • Ключевое слово global используется для объявления глобальной переменной внутри функции.
  • Нет необходимости использовать global для объявления глобальной переменной вне функции.
  • Переменные, на которые есть ссылка внутри функции, неявно являются глобальными.

Пример без использования глобального ключевого слова.

c = 10  


def mul():
    c = c * 10 
    print(c) 


mul() 

Вывод:

line 5, in mul
    c = c * 10
UnboundLocalError: local variable 'c' referenced before assignment

Этот код вернул ошибку, потому что была предпринята попытка присвоить значение глобальной переменной. Изменять значение можно только с помощью ключевого слова global.

c = 10  


def mul():
    global c
    c = c * 10 
    print("Значение в функции:", c)  

mul()  
print("Значение вне функции:", c)  

Вывод:

Значение в функции: 100
Значение вне функции: 100

Здесь переменная c была объявлена в функции mul() с помощью ключевого слова global. Ее значение умножается на 10 и становится равным 100. В процессе работы программы можно увидеть, что изменение значения внутри функции отражается на глобальном значении переменной.

Глобальные переменные в модулях Python

Преимущество использования ключевого слова global — в возможности создавать глобальные переменные и передавать их между модулями. Например, можно создать name.py, который бы состоял из глобальных переменных. Если их изменить, то изменения повлияют на все места, где эти переменные встречаются.

1. Создаем файл name.py для хранения глобальных переменных:

a = 10 
b = 20 
msg = "Hello World"

2. Создаем файл change.py для изменения переменных:

import name

name.a = 15  
name.b = 25
name.msg = "Dood bye"  

Меняем значения ab и msg. Эти переменные были объявлены внутри name, и для их изменения модуль нужно было импортировать.

3. В третий файл выводим значения измененных глобальных переменных.

import name
import change

print(name.a) 
print(name.b)
print(name.msg)

Значение изменилось. Вывод:

15
25
Dood bye

Global во вложенных функциях

Можно использовать ключевое слово global во вложенных функциях.

def add():
    a = 15
  
    def modify():
        global a
        a = 20

    print("Перед изменением:", a)
    print("Внесение изменений")
    modify()
    print("После изменения:", a)


add()
print("Значение a:", a)  

Вывод:

Перед изменением: 15
Внесение изменений
После изменения: 15
Значение a: 20

В этом коде значение внутри add() принимает значение локальной переменной x = 15. В modify() оно переназначается и принимает значение 20 благодаря global. Это и отображается в переменной функции add().

Добавить комментарий