
Шаг 5. Декораторы
Баллов за прохождение: 1
Декораторы
Декораторы - это функции, которые принимают в качестве аргумента другую функцию, добавляют к ней дополнительную функциональность и возвращают ее с измененным поведением.
Они так же изменяют работу не только функций, но и классов
Напишем декоратор, который будет замерять время выполнения функции
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Время выполнения: {end_time - start_time} секунд")
return result
return wrapper
Импортируем модуль time из стандартной библиотеки Python
Определим функцию-декоратор, назовем ее timer, а ее параметром будет другая функция
Внутри функции-декоратора определим еще одну функцию, которую обычно называют wrapper(обертка), она будет выполнять дополнительные действия перед и/или вызовом основной функцииб передадим ей args и kwargs
Засечем время перед вызовом нашей функции и после, а затем вычтем начальное время из конечного и получим время выполнения функции и вернем саму функцию
В функции-декораторе вернем нашу функцию-обертку
Применение декоратора
Замерим время выполнения медленной функции.
@timer
def slow_function():
for i in range(1, 999999999):
pass
return "Готово!"
print(slow_function())
Для того чтобы обернуть нашу функцию в декоратор, нужно написать его название вместе с символом @, что эквивалентно следующему синтаксису:
slow_function = timer(slow_function)
То есть мы буквально помещаем нашу функцию в обертку другой функции, которая расширяет функционал
На выходе мы получим нечто подобное
Благодаря декоратору мы получили время, за которое выполнилась наша функция, без дополнительного кода в теле нашей основной функции. Плюсом является то, что декоратор можно использовать неограниченное кол-во раз, и нам не придется плодить много кода.
Декоратор с аргументами
Мы так же можем написать декоратор, который будет принимать в себя аргументы. Давайте модифицируем наш декоратор таким образом, чтобы он выполнял функцию n раз, показывал сколько итераций прошло и сколько секунд понадобилось
import time
def timer(iters):
def decorator(func):
def wrapper(*args, **kwargs):
total = 0
for i in range(iters):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
total = total + (end_time - start_time)
print(f"Всего итерации:{iters}\nВсего {total} секунд")
return result
return wrapper
return decorator
Здесь мы объявили функцию timer с параметром iters, который указывает, сколько раз выполниться наша функция. Заметьте, функция timer не является декоратором, это обычная функция, которая возвращает декоратор
Обернем нашу функцию в декоратор, а в скобках после декоратора укажем кол-во итераций
@timer(10)
def slow_function():
for i in range(1, 99999999):
pass
return "Готово!"
print(slow_function())
Запустим программу и увидим примерно такой результат: