JavaRush /Курсы /Модуль 1: Python Core /Вся мощь декораторов

Вся мощь декораторов

Модуль 1: Python Core
8 уровень , 5 лекция
Открыта

6.1 Декораторы для методов классов

Декораторы также могут использоваться для методов классов. Важно помнить, что для методов классов необходимо правильно передавать аргументы self или cls.

Нюансы работы классов мы с вами еще не проходили, но хотелось бы, чтобы вы знали, что такая возможность у декораторов имеется.


def log_method_call(func):
    def wrapper(self, *args, **kwargs):
        print(f"Вызов метода {func.__name__}")
        return func(self, *args, **kwargs)

    return wrapper
        
class MyClass:
    @log_method_call
    def say_hello(self):
        print("Hello from MyClass!")
        
obj = MyClass()
obj.say_hello()

Объяснение

Декоратор (log_method_call): Этот декоратор принимает метод func и возвращает новую функцию wrapper, которая выводит сообщение перед вызовом метода.

Метод класса с декоратором (say_hello): Метод say_hello обернут декоратором log_method_call, что добавляет дополнительное поведение при его вызове.

Вывод:


Вызов метода say_hello
Hello from MyClass!

6.2 Несколько декораторов

Вы можете использовать несколько декораторов для одной функции, накладывая их друг на друга. Декораторы применяются в порядке, обратном их объявлению.


def decorator1(func):
    def wrapper():
        print("Декоратор 1")
        func()

    return wrapper
        
def decorator2(func):
    def wrapper():
        print("Декоратор 2")
        func()

    return wrapper
        
@decorator1
@decorator2
def say_hello():
    print("Hello!")
        
say_hello()

Объяснение

Декораторы (decorator1 и decorator2): Эти декораторы добавляют свои сообщения перед вызовом функции func.

Функция с декораторами (say_hello): Функция say_hello обернута обоими декораторами. Сначала применяется decorator2, затем decorator1.

Вывод:


# Декоратор 1
# Декоратор 2
Hello!

6.3 Встроенные декораторы

Python предоставляет несколько встроенных декораторов для стандартных задач, таких как статические методы, методы класса и свойства.

@staticmethod

Декоратор @staticmethod используется для создания статического метода, который не требует экземпляра класса для вызова.


class MyClass:
    @staticmethod
    def static_method():
        print("Это статический метод.")
        
MyClass.static_method()

@classmethod

Декоратор @classmethod используется для создания метода класса, который принимает класс (а не экземпляр) в качестве первого аргумента.


class MyClass:
    @classmethod
    def class_method(cls):
        print(f"Это метод класса {cls.__name__}.")
        
MyClass.class_method()

@property

Декоратор @property используется для создания геттеров, сеттеров и делетеров для атрибутов.


class MyClass:
    def __init__(self, value):
        self.hidden_value = value
        
    @property
    def value(self):
        return self.hidden_value
        
    @value.setter
    def value(self, new_value):
        self.hidden_value = new_value
        
obj = MyClass(10)
print(obj.value)  # Вывод: 10
obj.value = 20
print(obj.value)  # Вывод: 20

Это встроенные декораторы, их правильную работу обеспечивает сам интерпретатор Python.

6.4 Примеры использования декораторов

Логирование

Декораторы могут быть использованы для логирования вызовов функций и методов.


def log_call(func):
    def wrapper(*args, **kwargs):
        print(f"Вызов функции {func.__name__} с аргументами {args} и {kwargs}")
        return func(*args, **kwargs)

    return wrapper
        
@log_call
def add(x, y):
    return x + y
        
print(add(2, 3))

Контроль доступа

Декораторы могут быть использованы для контроля доступа к функциям и методам.


def require_authentication(func):
    def wrapper(*args, **kwargs):
        if not args[0].is_authenticated:
            raise PermissionError("Пользователь не аутентифицирован.")
        return func(*args, **kwargs)
        
    return wrapper
        
class User:
    def __init__(self, is_authenticated):
        self.is_authenticated = is_authenticated
        
    @require_authentication
    def view_profile(self):
        print("Профиль пользователя")
        
user = User(is_authenticated=True)
user.view_profile()  # Успешный вызов
        
user2 = User(is_authenticated=False)
user2.view_profile()  # PermissionError: Пользователь не аутентифицирован.

Кэширование

Декораторы могут быть использованы для кэширования результатов функции.


def cache(func):
    cached_results = {}

    def wrapper(*args):
        if args in cached_results:
            return cached_results[args]
        result = func(*args)
        cached_results[args] = result
        return result

    return wrapper

@cache
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(35))
2
Задача
Модуль 1: Python Core, 8 уровень, 5 лекция
Недоступна
Множество декораторов.
Множество декораторов.
2
Задача
Модуль 1: Python Core, 8 уровень, 5 лекция
Недоступна
Длительность работы.
Длительность работы.
Комментарии (38)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Alex Уровень 30
16 марта 2026
это peasедец
Дмитрий Уровень 1
20 декабря 2025
А кто-то может объяснить почему порядок обратный? "Декораторы применяются в порядке, обратном их объявлению." Мы же не читаем код снизу вверх? Объявили декоратор1, потом декоратор2, потом функцию...

@decorator1
@decorator2
def some_function():
    ...
Оно так и выполняется. Сначала запускается decorator1, который запускает decorator2, который запускает функцию, функция заканчивает работу, заканчивает работу decorator2, заканчивает работу decorator1. Или я что-то не понимаю?
Александр Уровень 22
10 февраля 2026
decorator2 делает вначале свою обертку wrapper(2), затем decorator1 делает свою обертку wrapper(1)
EvgenyXIV Уровень 31
2 апреля 2026
Так понятней будет, наверное: 1. decorator2(func) делает вначале свою обертку wrapper() функции func и возвращает функцию wrapper. Результат работы decorator2 это decorator2 hello 2. затем decorator1(func) делает свою обертку wrapper() функции-обёртки wrapper() декоратора decorator2 и выводит результат decorator1 decorator2 hello Иными словами по-русски :) У декоратора decorator2 аргумент func = say_hello У декоратора decorator1 аргумент func = wrapper() декоратора decorator2
Mongoose Уровень 25
19 декабря 2025
def log_method_call(func): def wrapper(self, *args, **kwargs): print(f"Вызов метода {func.__name__}") return func(self, *args, **kwargs) return wrapper class MyClass: @log_method_call def say_hello(self): print("Hello from MyClass!") obj = MyClass() obj.say_hello() То есть в сторонний класс вгрызается декоратор и контролирует поведение метода класса?!
Александр Уровень 22
10 февраля 2026
Точно подмечено!! log_method_call явно использует self для этого!! GPT: "def wrapper(self, *args, **kwargs): напрямую прописывает self. Это делает код понятнее для тех, кто читает его в контексте ООП. Но даже если бы вы написали универсально: def wrapper(*args, **kwargs): То self всё равно бы попал внутрь, просто он стал бы первым элементом кортежа args[0]."
AndreyCDO Уровень 18
8 ноября 2025
Всё было хорошо, пока не началась тема с функциями высших порядков и декораторами... В этот момент я подумал что где-то очень медленно моргнул... И только когда начал читать комментарии понял, что это не во мне дело. К счастью, есть ИИ, который очень хорошо построчно объясняет что тут вообще происходит! Очень рекомендую.
Миракбар Уровень 17
22 октября 2025
import time def time_decorator(func): def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) elapsed = time.time() - start print(elapsed) return result return wrapper @time_decorator def compute_square(n): print(n ** 2) time.sleep(1) compute_square(3)
shinobi Уровень 20
29 июля 2025
Отлично, 10 лекций где задачи это ктрл в ктрл ц, причём 1в1, и тут бац - сделайте задачу про время. а какую библиотеку импортировать и как с ней работать - это уже сами подумайте. Браво, автор, небось нейронка по ошибке накинула в примеры тайм, и автор как обычно слизывая с нейронки не удосужился ничего сделать или поменять, и просто вставил
Anonymous #6475281 Уровень 29
4 марта 2026
Применение подсчета времени было в одной из предыдущих лекций про генераторы :)
Slevin Уровень 59
1 июля 2025
Прикиньте рассказывать про встроенные декораторы - методы классов, не рассказав абсолютно ничего про классы, что это такое и как выглядит... А нам и прикидывать не нужно 😂🤣
Slevin Уровень 59
1 июля 2025
Также, во втором задании, воспользуемся библиотекой, про которую вы ничего не знаете и не слышали. Удачи! 🤣🤣🤣
Tatiana Уровень 1
24 июня 2025

import time

def time_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        time.sleep(1)
        result = func(*args, **kwargs)
        elapsed = time.time() - start
        print(elapsed)
        return result
    return wrapper

@time_decorator
def compute_square(n):
    print(n ** 2)

compute_square(3)
EvgenyXIV Уровень 31
2 апреля 2026
вообще-то логичнее задержку реализовать в самой функции квадратов compute_square, иначе смысл декораторов исчезает)
SWK Уровень 26
3 апреля 2025
"чтобы можно было наблюдать за работой декораторов", как написано в задаче №1, нужно наворотить что-то такое, как минимум:

def decorator1(func):
    def wrapper1(*args, **kwargs):
        print(f"Call wrapper1")
        print(f"Вызов функции {func.__name__} с аргументами {args} и {kwargs}")
        result = func(*args, **kwargs)
        print(f"End wrapper1")
        return result

    return wrapper1

def decorator2(func):
    def wrapper2(*args, **kwargs):
        print(f"Call wrapper2")
        print(f"Вызов функции {func.__name__} с аргументами {args} и {kwargs}")
        result = func(*args, **kwargs)
        print(f"End wrapper2")
        return result

    return wrapper2

@decorator1
@decorator2
def say_hello():
    print("Hello!")

say_hello()

Не надо удалять это "как решение", это не решение, здесь много лишнего.
Slevin Уровень 59
1 июля 2025
Хотел выложить такое же, пока не дописал вывод декоратора После функции - не особо понимал их формат вывода: func = decorator1(decorator2(func))
Mongoose Уровень 25
19 декабря 2025
Декораторы вращают функцию. Смотреть без смс и регистрации
Дмитрий Уровень 27
25 февраля 2025
В первой задаче добавьте требование, чтобы функция say_hello вызывала функцию print, раз уж отсутствие этой функции является условием не принятия задачи.