На этом шаге мы рассмотрим понятие декоратора и примеры использования декораторов.
Декораторы позволяют изменить поведение обычных функций - например, выполнить какие-либо действия перед выполнением функции. Рассмотрим это на примере:
def deco(f): # Функция-декоратор print("Вызвана функция func()") return f # Возвращаем ссылку на функцию @deco def func (x): return "x = {0}".format(x) print(func(10))
Результат выполнения примера приведен на рисунке 1.
Рис.1. Результат работы приложения
В этом примере перед определением функции func() указывается название функции deco() с предваряющим символом @:
@deco
Таким образом, функция deco() становится декоратором функции func(). В качестве параметра функция-декоратор принимает ссылку на функцию, поведение которой необходимо изменить, и должна возвращать ссылку на ту же функцию или какую-либо другую. Наш предыдущий пример эквивалентен следующему коду:
def deco(f): print("Вызвана функция func()") return f def func(x): return "x = {0}".format(x) # Вызываем функцию func() через функцию deco() print(deco(func)(10))
Перед определением функции можно указать сразу несколько функций-декораторов. Для примера обернем функцию func() в два декоратора: deco1() и deco2():
def deco1(f): print("Вызвана функция deco1()") return f def deco2(f): print("Вызвана функция deco2()") return f @deco1 @deco2 def func (x): return "x = {0}".format(x) print(func(10))
Результат выполнения примера приведен на рисунке 2.
Рис.2. Результат работы приложения
Использование двух декораторов эквивалентно следующему коду:
func = deco1(deco2(func))
Здесь сначала будет вызвана функция deco2(), а затем функция deco1(). Результат выполнения будет присвоен идентификатору funс.
В качестве еше одного примера использования декораторов рассмотрим выполнение функции только при правильно введенном пароле:
passw = input("Введите пароль: ") def test_passw(p): def deco(f): if p == "10": # Сравниваем пароли return f else: return lambda: "Доступ закрыт" return deco # Возвращаем функцию-декоратор @test_passw(passw) def func(): return "Доступ открыт" print(func()) # Вызываем функцию
В этом примере после символа @ указана не ссылка на функцию, а выражение, которое возвращает декоратор. Иными словами, декоратором является не функция test_passw(), а результат ее выполнения (функция deco()). Если введенный пароль является правильным, то выполнится функция func(), в противном случае будет выведена надпись "Доступ закрыт", которую возвращает анонимная функция (рисунок 3).
Рис.3. Результат работы приложения
На следующем шаге мы рассмотрим рекурсию.