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

Где применяется замыкание?

2.0 Middle🔥 161 комментариев
#Python Core

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

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

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

Замыкания (Closures) в Python: практическое применение

Замыкание — это функция, которая запоминает значения переменных из области видимости, в которой она была определена, даже после завершения этой функции. Это мощный механизм, используемый повсеместно в профессиональной разработке.

1. Создание параметризованных функций

Одно из самых популярных применений — генерация специализированных функций:

def make_multiplier(n):
    def multiplier(x):
        return x * n
    return multiplier

triple = make_multiplier(3)
double = make_multiplier(2)

print(triple(5))  # 15
print(double(5))  # 10

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

2. Декораторы (основной случай применения)

Все декораторы в Python работают на замыканиях:

def timer(func):
    import time
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        elapsed = time.time() - start
        print(f"{func.__name__} took {elapsed:.2f}s")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(2)
    return "Done"

slow_function()
# slow_function took 2.00s

Замыкание сохраняет ссылку на func, хотя тот был передан как параметр.

3. Callback'и и обработчики событий

Частое применение в асинхронных системах и обработчиках:

def create_event_handler(user_id, action_log):
    def handle_click(event):
        timestamp = datetime.now()
        action_log.append({
            "user_id": user_id,
            "event": event.type,
            "timestamp": timestamp
        })
    return handle_click

actions = []
click_handler = create_event_handler(user_id=123, action_log=actions)
click_handler(Event(type="button_click"))

4. Приватные переменные и инкапсуляция

Python не имеет встроенных приватных переменных, но замыкания помогают эмулировать это:

def create_account(initial_balance):
    balance = initial_balance  # приватная переменная
    
    def deposit(amount):
        nonlocal balance
        balance += amount
        return balance
    
    def withdraw(amount):
        nonlocal balance
        if amount > balance:
            raise ValueError("Insufficient funds")
        balance -= amount
        return balance
    
    def get_balance():
        return balance
    
    return {"deposit": deposit, "withdraw": withdraw, "get_balance": get_balance}

account = create_account(1000)
print(account["get_balance"]())  # 1000
account["deposit"](500)           # 1500
# account.balance невозможно изменить напрямую

5. Кеширование (Memoization)

Замыкания часто используются для реализации кешей:

def memoize(func):
    cache = {}  # замкнутая переменная
    
    def wrapper(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]
    
    return wrapper

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

print(fibonacci(35))  # вычисляется мгновенно благодаря кешу

6. Фабрики объектов в зависимостях

Для внедрения зависимостей:

def create_database_connector(connection_string):
    db = connect(connection_string)  # замкнутая зависимость
    
    def query(sql):
        return db.execute(sql)
    
    def close():
        db.close()
    
    return {"query": query, "close": close}

# В тестах можно подменить
db_prod = create_database_connector("postgres://prod")
db_test = create_database_connector("sqlite://test.db")

7. Частичное применение функций (Currying)

Функциональный стиль программирования:

def power(base):
    def exponent(exp):
        return base ** exp
    return exponent

square = power(2)  # замыкание с base=2
cube = power(3)

print(square(5))   # 32
print(cube(5))     # 243

Критические особенности:

  • Ключевое слово nonlocal — необходимо для изменения переменных внешней области
  • Утечки памяти — замыкание держит ссылки на переменные, что может предотвратить их сборку мусора
  • Производительность — замыкания немного медленнее обычных функций из-за поиска переменных

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