English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Os decoradores aceitam uma função, adicionam algumas funcionalidades e a retornam. Neste artigo, você aprenderá como criar decoradores e por que usá-los.
Python tem uma função interessante chamadaDecoradores,pode adicionar funcionalidades ao código existente.
Também chamado deMeta-programação,Porque parte do programa tenta modificar outro parte do programa no tempo de compilação.
Чтобы понять декораторы,我们必须 сначала понять некоторые базовые знания Python.
Мы должны принять тот факт, что всё в Python являетсяОбъекты. Названия, которые мы определяем, просто привязаны к этим объектам в качестве идентификаторов.ФункцииЭто также не исключение, они также являются объектами (с свойствами). Разные имена могут быть привязаны к одному и тому же объекту функции.
Это пример.
def first(msg): print(msg) first("Hello") second = first second("Hello")
Когда вы запускаете код, эти функции first и second дают одинаковый вывод. Здесь имена first и second указывают на одинаковые объекты функций.
Теперь ситуация стала несколько сложнее, так как можно передавать функции в качестве параметров других функций.
Если вы использовали в Python функции, такие как map, filter и reduce, то вы уже знаете это.
Эти функции, которые являются параметрами других функций, также называютсяВысокий уровень функций. Это пример такой функции.
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() # Вывод "Hello" new()
Здесь, is_returned() - это вложенная функция, которая определяет и возвращает себя каждый раз, когда мы вызываем is_drawn().
В конце концов, мы должны понятьКлонируемые в Python.
Функции и методы называютсяВызываемые,Потому что их можно вызывать.
На самом деле, любая объект, реализующий особый метод __call__(), называется вызываемым. Таким образом, в наиболее базовом смысле, декораторы являются вызываемыми и могут возвращать вызываемые.
В основном, декораторы принимают функцию, добавляют к ней некоторые функции и возвращают её.
def make_pretty(func): def inner(): print("Я был декорирован") func() возврат inner def ordinary(): print("Я обычная функция")
При выполнении следующего кода в shell,
>>> ordinary() Я обычная функция >>> # Давайте декорируем эту обычную функцию >>> pretty = make_pretty(ordinary) >>> pretty() Я был декорирован Я обычная функция
В примере, показанном выше, make_pretty() является декоратором. В шаге назначения.
pretty = make_pretty(ordinary)
Функция ordinary() была декорирована, и возвращенная функция была命名为 pretty.
Мы можем увидеть, что decorator функция добавляет некоторые новые функции в исходную функцию. Это похоже на упаковку подарка. Декоратор играет роль упаковщика. Свойства подарка (внутри) не изменяются. Но теперь он выглядит красиво (с момента упаковки).
Обычно мы декорируем функцию и заново присваиваем ее
ordinary = make_pretty(ordinary).
Это распространенная конструкция, поэтому Python имеет синтаксис для ее упрощения.
Мы можем использовать символ @ вместе с именем декораторной функции и поместить его над определением функции, которую мы хотим декорировать. Например,
@make_pretty def ordinary(): print("Я обычная функция")
Это эквивалентно
def ordinary(): print("Я обычная функция") ordinary = make_pretty(ordinary)
Это просто синтаксический сахар для реализации декоратора.
Этот декоратор прост и подходит только для функций без параметров. Что если наши функции имеют такие параметры?
def divide(a, b): return a/b
Эта функция имеет два параметра:aиb. Мы знаем, что если мы我们将bЕсли передается 0, то возникает ошибка.
>>> divide(2,5) 0.4 >>> divide(2,0) Traceback (последний вызов в конце): ... ZeroDivisionError: деление на ноль
Теперь давайте создадим декоратор, чтобы проверить, приведет ли это к ошибке.
def smart_divide(func): def inner(a,b): print("Я хочу сделать деление", a, "и", b) if b == 0: print("О, не могу поделить") return return func(a,b) возврат inner @smart_divide def divide(a,b): return a/b
Если arises ошибка, новая реализация вернет None.
>>> divide(2,5) Я хочу сделать деление 2 и 5 0.4 >>> divide(2,0) Я хочу сделать деление 2 и 0 Ой! Не можно делить
Таким образом, мы можем декорировать функции с параметрами.
Шарпый наблюдатель заметит, что параметры вложенной функции в декораторе inner() такие же, как и параметры декорируемой функции. учитывая это, теперь мы можем сделать универсальный декоратор, который может использовать любое количество параметров.
В Python это магия достигается через completion function(*args, **kwargs). Таким образом, args — это позиционные параметрыТупльа kwargs — это ключевые параметрыСловарь. Пример такого декоратора —
def works_for_all(func): def inner(*args, **kwargs): print("Я могу декорировать любую функцию") возврат func(*args, **kwargs) возврат inner
Можем ли мы связать несколько декораторов в Python.
Это означает, что функция может быть декорирована несколькими (или одинаковыми) декораторами. Нам нужно только поместить декораторы над нужной функцией.
def star(func): def inner(*args, **kwargs): print("*" * 30) func(*args, **kwargs) print("*" * 30) возврат inner def percent(func): def inner(*args, **kwargs): print("%" * 30) func(*args, **kwargs) print("%" * 30) возврат inner @star @percent def printer(msg): print(msg) printer("Привет")
Это даст вывод.
****************************** %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Привет %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ******************************
верхней грамматике,
@star @percent def printer(msg): print(msg)
Это эквивалентно
def printer(msg): print(msg) printer = star(percent(printer))
Порядок链接 декораторов очень важен. Если мы будем использовать обратный порядок,
@percent @star def printer(msg): print(msg)
Выполнение будет производиться
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ****************************** Привет ****************************** %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%