Python позволяет определять функции *внутри* других. Зачем? Чтобы передавать поведение, создавать замыкания, делать partial-функции и, конечно, писать декораторы.
✅ Вложенные функции = функции внутри функций
def greet_me(name="друг"):
def greet():
print("Привет,", name)
greet()
🚩 Внутренняя
greet() знает о name, потому что захватила его из внешней функции. Это и есть замыкание — функция «помнит» переменные.✅ Функция возвращает функцию
def greet_me(name):
def greet():
print("Привет,", name)
return greet
greet_ivan = greet_me("Иван")
greet_ivan() # Привет, Иван
🚩
greet_ivan — это не результат, а сама функция! Причём она «помнит», что name = Иван. Удобно, если нужно повторно вызывать с теми же параметрами.✅ Создаём функции с «настроенным поведением»
def make_adder(x):
def add(y):
return x + y
return add
add5 = make_adder(5)
add5(10) # ➡️ 15
🚩 Мы создали «фабрику» функций.
add5 — это функция, которая всегда добавляет 5. Можно так же легко сделать add10, add100 и т.д.✅ Своя версия partial-функции
def partial(func, *args, **kwargs):
def new_func(*a, **kw):
return func(*args, *a, **kwargs, **kw)
return new_func
bin_to_int = partial(int, base=2)
bin_to_int("1101") # ➡️ 13
🚩 Мы зафиксировали аргумент
base=2 и получили удобную функцию bin_to_int(), которая всегда читает двоичное число. Быстро и понятно!✅ Декораторы работают точно так же
def log(func):
def wrapper(*args, **kwargs):
print("Вызов", args, kwargs)
result = func(*args, **kwargs)
print("Результат", result)
return result
return wrapper
🚩
log — это функция, которая возвращает функцию-обёртку. Эта обёртка добавляет логирование вокруг вызова оригинальной функции. Никакой магии — только вложенные функции и замыкание.Что нужно запомнить:
✔️ Вложенные функции — удобный способ передавать и «запоминать» контекст
✔️ Замыкание — функция несёт с собой значения переменных
✔️ partial и декораторы — мощные приёмы, основанные на этих идеях
Библиотека питониста #буст