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

Что хранится в пространстве имен в Python?

1.7 Middle🔥 201 комментариев
#DevOps и инфраструктура#Django

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

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

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

Пространство имён в Python

Пространство имён (namespace) — это словарь, который сопоставляет имена объектам. Всё в Python является объектом, и пространство имён позволяет интерпретатору находить и управлять этими объектами. Это критически важная концепция для понимания области видимости и разрешения имён.

Типы пространств имён

В Python существует четыре основных типа пространств имён, каждое со своей областью видимости:

1. Встроенное пространство имён (Built-in)

# Встроенное пространство имён содержит встроенные функции и типы
import builtins

print(dir(builtins))  # Выведет все встроенные имена

# Примеры встроенных функций
print(len)  # <built-in function len>
print(int)  # <class int>
print(str)  # <class str>
print(Exception)  # <class Exception>

# Можем просмотреть все встроенные имена
built_ins = [name for name in dir(builtins) if not name.startswith(_)]
print(f"Встроенных имён: {len(built_ins)}")

2. Глобальное пространство имён (Global)

# Глобальное пространство имён модуля
x = 10  # Глобальная переменная

def global_namespace_example():
    # Функция видит глобальные переменные
    print(f"x из глобального пространства: {x}")

# Просмотр глобального пространства имён
print(f"Глобальные переменные: {globals()}")
print(f"Ключи: {list(globals().keys())}")

global_namespace_example()

# Используем global для изменения глобальной переменной
def modify_global():
    global x
    x = 20
    print(f"Изменённое x: {x}")

modify_global()
print(f"x теперь: {x}")

3. Локальное пространство имён (Local)

def function_with_local_namespace():
    local_var = 42  # Локальная переменная
    nested_var = "text"  # Ещё одна локальная переменная
    
    print(f"Локальные переменные: {locals()}")
    
    def nested_function():
        nested_local = 100
        print(f"Локальные переменные вложенной функции: {locals()}")
    
    nested_function()

function_with_local_namespace()

# Локальные переменные не видны вне функции
try:
    print(local_var)
except NameError:
    print("NameError: local_var не определена на глобальном уровне")

4. Замыкание (Enclosing)

def outer():
    enclosing_var = "I am enclosing"  # Переменная промежуточного уровня
    
    def inner():
        # Доступ к переменной из enclosing scope
        print(f"Вложенная функция видит: {enclosing_var}")
        print(f"Локальные переменные: {locals()}")
    
    inner()
    
    return inner

inner_func = outer()
inner_func()  # Замыкание сохраняет доступ к enclosing_var

LEGB правило разрешения имён

Python использует правило LEGB для поиска переменных:

x = "global"  # Global

def outer():
    x = "enclosing"  # Enclosing
    
    def inner():
        x = "local"  # Local
        print(f"x = {x}")  # Local
    
    def inner2():
        print(f"x = {x}")  # Enclosing
    
    inner()  # Выведет: x = local
    inner2()  # Выведет: x = enclosing

print(f"x = {x}")  # Global: x = global
outer()

# Пример с nonlocal
def outer2():
    count = 0
    
    def increment():
        nonlocal count  # Модифицирует переменную enclosing scope
        count += 1
        return count
    
    print(increment())  # 1
    print(increment())  # 2
    print(increment())  # 3

outer2()

Пространства имён в классах

class MyClass:
    class_var = 10  # Переменная класса
    
    def __init__(self, name):
        self.instance_var = name  # Переменная экземпляра
    
    def method(self):
        method_local = 42
        print(f"Локальное пространство метода: {locals()}")

# Просмотр пространств имён класса
print(f"Пространство имён класса: {MyClass.__dict__}")
print(f"Ключи: {list(MyClass.__dict__.keys())}")

# Просмотр пространства имён экземпляра
obj = MyClass("Alice")
print(f"Пространство имён экземпляра: {obj.__dict__}")
print(f"Ключи: {list(obj.__dict__.keys())}")

obj.method()

Модули как пространства имён

# Каждый модуль имеет своё пространство имён
import math
import os

# Просмотр пространства имён модуля
print(f"Модуль math содержит: {dir(math)}")
print(f"Функции math: {[name for name in dir(math) if not name.startswith(_)]}")

# Доступ к переменным модуля через __dict__
print(f"Пространство имён модуля: {math.__dict__.keys()}")

# Импорт конкретных имён
from math import pi, sqrt
print(f"pi = {pi}")
print(f"sqrt(16) = {sqrt(16)}")

Динамическое управление пространствами имён

# Используем globals() и locals() для динамического доступа

def dynamic_namespace():
    local_var = "local"
    
    # Просмотр переменной через locals()
    print(f"Переменная есть в locals: {local_var in locals()}")
    
    # Динамическое создание переменной
    locals()["dynamic_var"] = "dynamically created"
    
    # Внимание: изменение locals() обычно не работает как ожидается
    print(f"dynamic_var определена: {locals()}")

dynamic_namespace()

# Более надёжный способ - использовать exec()
def exec_example():
    namespace = {}
    exec("x = 10; y = 20; z = x + y", namespace)
    print(f"Результат: {namespace[z]}")

exec_example()

# Использование getattr/setattr для динамического доступа
class Config:
    pass

config = Config()
setattr(config, debug, True)
setattr(config, timeout, 30)

print(f"debug = {getattr(config, debug)}")
print(f"timeout = {getattr(config, timeout)}")
print(f"Пространство имён объекта: {config.__dict__}")

Практические примеры

# Пример 1: Счётчик с замыканием
def make_counter():
    count = 0
    
    def increment():
        nonlocal count
        count += 1
        return count
    
    return increment

counter = make_counter()
print(counter())  # 1
print(counter())  # 2
print(counter())  # 3

# Пример 2: Кэширование через замыкание
def cache_decorator():
    cache = {}  # Находится в enclosing namespace
    
    def decorator(func):
        def wrapper(n):
            if n not in cache:
                cache[n] = func(n)
            return cache[n]
        return wrapper
    
    return decorator

make_cache = cache_decorator()

@make_cache()
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

Важные правила

  1. Встроенные имена всегда доступны, но могут быть затенены локальными
  2. Глобальные имена видны во всём модуле
  3. Локальные имена существуют только в функции
  4. Enclosing имена видны во вложенных функциях (замыкания)
  5. LEGB правило определяет порядок поиска

Понимание пространств имён критично для работы с переменными, функциями и модулями в Python.