Декораторы в Python: улучшайте функции экспертными техниками
Декораторы в Python
Декораторы позволяют оборачивать функции в переиспользуемую логику, делая код более модульным, читаемым и поддерживаемым. В этом руководстве мы строим, объясняем и применяем декораторы в реальных сценариях.
Видео: @Декораторы в Python
Декораторы в Python
Декораторы Python — мощный метапрограмминговый инструмент, позволяющий добавлять поведение функциям или классам в момент определения. Поскольку в Python всё — объекты, включая функции и классы, декораторы работают, принимая один вызываемый объект, оборачивая его в другой и возвращая новый вызываемый.
Предварительные знания для изучения декораторов
Прежде чем углубляться, вы должны быть комфортны с тем, что в Python функции — объекты первого класса. Имена — просто ссылки, привязанные к объектам; одна и та же функция может ссылаться несколькими именами.
def first(msg):
print(msg)
first("Hello")
second = first
second("Hello")
Вывод
Hello Hello
Функции можно передавать как аргументы, возвращать из других функций и даже вкладывать в другие функции. Эти концепции — функции высшего порядка, вложенные функции и замыкания — являются строительными блоками декораторов.
def inc(x):
return x + 1
def dec(x):
return x - 1
def operate(func, x):
result = func(x)
return result
Использование:
>>> operate(inc, 3)
4
>>> operate(dec, 3)
2
def is_called():
def is_returned():
print("Hello")
return is_returned
new = is_called()
new()
Вывод
Hello
Понимание замыканий ключево: вложенная функция сохраняет доступ к объемлющей области видимости, что именно используют декораторы для хранения метаданных или изменения поведения.
Возвращаемся к декораторам
В Python декоратор — это просто вызываемый объект, принимающий функцию (или другой вызываемый) и возвращающий новый вызываемый. Возвращённая функция обычно оборачивает оригинальную, добавляя или изменяя функциональность до или после вызова.
def make_pretty(func):
def inner():
print("I got decorated")
func()
return inner
def ordinary():
print("I am ordinary")
Пример использования:
>>> ordinary()
I am ordinary
>>> pretty = make_pretty(ordinary)
>>> pretty()
I got decorated
I am ordinary
Паттерн декоратора сохраняет семантику оригинальной функции нетронутой, пока расширяя её. Чтобы избежать ручного переприсваивания, Python предоставляет синтаксический сахар с символом @:
@make_pretty
def ordinary():
print("I am ordinary")
Это эквивалентно:
def ordinary():
print("I am ordinary")
ordinary = make_pretty(ordinary)
Декорирование функций с параметрами
Многие декораторы должны обрабатывать произвольные аргументы. Синтаксис *args и **kwargs позволяет захватывать любые позиционные или именованные аргументы и передавать их без изменений.
def works_for_all(func):
def inner(*args, **kwargs):
print("I can decorate any function")
return func(*args, **kwargs)
return inner
Обработка граничных случаев — ещё одно частое применение декораторов. Например, защита от деления на ноль:
def smart_divide(func):
def inner(a, b):
print("I am going to divide", a, "and", b)
if b == 0:
print("Whoops! cannot divide")
return
return func(a, b)
return inner
@smart_divide
def divide(a, b):
print(a / b)
Использование:
>>> divide(2, 5)
I am going to divide 2 and 5
0.4
>>> divide(2, 0)
I am going to divide 2 and 0
Whoops! cannot divide
Цепочки декораторов в Python
Декораторы можно накладывать друг на друга. Порядок применения важен, так как каждый декоратор получает функцию, возвращённую тем, что под ним.
def star(func):
def inner(*args, **kwargs):
print("*" * 30)
func(*args, **kwargs)
print("*" * 30)
return inner
def percent(func):
def inner(*args, **kwargs):
print("%" * 30)
func(*args, **kwargs)
print("%" * 30)
return inner
@star
@percent
def printer(msg):
print(msg)
Результат:
****************************** %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Hello %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ******************************
Смена порядка меняет окружающие паттерны, демонстрируя, как наложение декораторов влияет на поведение.
Python
- Освоение типов данных в Python: практическое руководство
- Мастерство операторов Python: Полное руководство
- Оператор pass в Python: практическое руководство
- Аргументы функций в Python: позиционные, именованные и параметры по умолчанию
- Lambda-функции в Python: практическое руководство по анонимным функциям
- Освоение лямбда-функций Python: практические примеры и лучшие практики
- Функция abs() в Python: вычисление абсолютных значений для чисел и комплексных чисел
- Функция round() в Python: подробное объяснение с практическими примерами
- Освоение функции range() в Python: от основ к продвинутым сценариям
- Освоение функции map() в Python: синтаксис, примеры и лучшие практики