← Назад к вопросам

Как называются переменные вне функции, с точки зрения Scope?

1.3 Junior🔥 261 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Scope переменных в Python (LEGB правило)

Переменные вне функции называются глобальными (Global scope), но это только одна часть системы видимости в Python. Полная иерархия scope называется LEGB правилом.

LEGB: Порядок поиска переменных

При обращении к переменной Python ищет её в следующем порядке:

L — Local (локальный scope функции)
E — Enclosing (замыкание — внешняя функция)
G — Global (глобальный scope модуля)
B — Built-in (встроенные переменные Python)

1. Local (L) — Локальный scope

Переменные, определённые внутри функции:

def foo():
    x = 10  # Local scope
    print(x)  # 10

foo()
print(x)  # NameError: x не определена

2. Enclosing (E) — Scope замыкания

Переменные из внешней функции (вложенные функции):

def outer():
    x = 10  # Enclosing scope для inner
    
    def inner():
        print(x)  # 10 (ищет в Enclosing)
    
    inner()

outer()

Цепочка поиска:

def outer():
    x = "outer"
    
    def middle():
        x = "middle"
        
        def inner():
            x = "inner"
            print(x)  # inner (Local)
        
        inner()
        print(x)  # middle (Local для middle)
    
    middle()
    print(x)  # outer (Local для outer)

outer()

3. Global (G) — Глобальный scope

Переменные на уровне модуля (вне функций и классов):

x = 100  # Global scope

def foo():
    print(x)  # 100 (ищет в Global)

foo()

4. Built-in (B) — Встроенные имена

Встроенные функции и типы Python:

print(len)   # <built-in function len>
print(int)   # <class int>
print(True)  # True

# Это встроенные имена в scope B

Полный пример LEGB

x = "Global"  # G

def outer(param):
    x = "Enclosing"  # E
    
    def inner():
        x = "Local"  # L
        y = param  # E (параметр — тоже Enclosing для inner)
        z = len([1, 2, 3])  # B (встроенная функция len)
        
        print(f"L: {x}, E: {y}, G: найдена при нужде, B: {z}")
    
    inner()

outer("param_value")
# L: Local, E: param_value, G: найдена при нужде, B: 3

Проверка scope с помощью globals() и locals()

x = "global"

def foo():
    y = "local"
    print(locals())   # {"y": "local"}
    print(globals())  # Очень большой словарь со всеми глобальными переменными

foo()

Функция vars() для class

class MyClass:
    class_var = "class"
    
    def __init__(self):
        self.instance_var = "instance"

obj = MyClass()
print(vars(obj))  # {"instance_var": "instance"}
print(vars(MyClass))  # Очень много, включая class_var

dir() — все имена в scope

def foo():
    x = 10
    print(dir())  # Список всех доступных имён

foo()

Конфликты и приоритет

Если переменная определена в нескольких scope, используется первая найденная по LEGB:

x = "Global"

def outer():
    x = "Enclosing"
    
    def inner():
        x = "Local"
        print(x)  # "Local" (L первый в LEGB)
    
    inner()

outer()

Ключевые слова: global и nonlocal

global — обращение к Global scope:

x = 0

def increment():
    global x  # Теперь x относится к Global scope
    x += 1

increment()
print(x)  # 1

nonlocal — обращение к Enclosing scope:

def outer():
    x = 0
    
    def inner():
        nonlocal x  # Теперь x относится к Enclosing scope
        x += 1
    
    inner()
    print(x)  # 1

outer()

Задача на понимание LEGB

a = "A"

def level1():
    a = "L1"
    
    def level2():
        a = "L2"
        
        def level3():
            print(a)  # Что выведется?
        
        level3()
    
    level2()

level1()
# Ответ: L2 (используется ближайший scope)

Без явного определения в Local

a = "Global"

def foo():
    print(a)  # "Global" (ищет в Enclosing, потом Global)

foo()

Когда это становится сложным

g = "global"

def outer():
    e = "enclosing"
    
    def inner():
        # Если мы хотим читать из разных scope:
        print(g)  # "global" — читаем из G
        print(e)  # "enclosing" — читаем из E
        
        # Но если мы хотим ПИСАТЬ в них:
        # g = "new"  # Создаст новый L (не Global!)
        # global g  # Нужно явно указать
        # e = "new"  # Создаст новый L (не Enclosing!)
        # nonlocal e  # Нужно явно указать
    
    inner()

outer()

Инспекция scope

import inspect

def outer():
    x = 10
    
    def inner():
        print(inspect.currentframe().f_locals)  # Local scope
        print(inspect.currentframe().f_globals)  # Global scope
    
    inner()

outer()

Резюме

  • Global scope — переменные вне функций
  • Local scope — внутри функции
  • Enclosing scope — во вложенных функциях
  • Built-in scope — встроенные имена
  • LEGB правило определяет порядок поиска
  • global/nonlocal для явной работы с другими scope

Понимание scope критично для избегания ошибок и написания предсказуемого кода.

Как называются переменные вне функции, с точки зрения Scope? | PrepBro