• burger-icon

    Шаг 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())

    Запустим программу и увидим примерно такой результат:

     

    Для решения задачи, Зарегистрируйтесь или Войдите на сайт.