Форум программистов, компьютерный форум, киберфорум
Фаер
Войти
Регистрация
Восстановить пароль

Python. Декораторы.

Запись от Фаер размещена 13.11.2012 в 16:00
Показов 4632 Комментарии 0

В предыдущих записях Мы говорили о клонировании и наследовании - приёмах, позволяющих изменять объекты и классы. Разумеется, Python предоставляет и другие инструменты, используя которые, можно прийти к тому же результату. Одним из таких инструментов, являются декораторы.

Декоратор - программный шаблон, оборачивающий некий объект дополнительным уровнем логики. Одним словом, обёртка. Едва ли можно сказать, что использование декораторов упрощает разработку, однако многие программисты находят их очень удобными, а значит есть смысл рассказать о них.

В первую очередь, давайте разберём декорирование функций. Нужно заметить, что в Python'е функции являются объектами, их можно передать в качестве аргументов другим функциям, что, в общем-то, и происходит при оборачивании. То есть, декоратор - это функция, принимающая другую функцию в качестве аргумента:

Python
1
2
3
4
5
6
7
8
9
10
11
12
def decor(func):
    print('Done')
    return func
 
@decor
def func(t):
    t=t+5
    return t
 
otvet=func(5)
print(otvet)
input()
Как видите, декоратор decor() описывается, как самая обыкновенная подпрограмма. В качестве аргумента он принимает функцию func(), ту самую, которую Мы оборачиваем. Имя оборачивающего декоратора указывается прямо перед описанием оборачиваемой функции со значком @.

В результате, обращение к функции func происходит не напрямую, а через обёртку. В Нашем случае, сначала выполняется команда print('Done'), описанная в декораторе, а уже потом вызывается сама функция(return func).

Казалось бы, всё хорошо. Однако есть одна мелочь, которая несколько омрачает светлый образ декораторов. Дело в том, что декоратор и вложенная в него функция имеют разные пространства имён. Аргументы, переданные func(), недоступны на уровне decor'а. Исправить этот недочёт можно, но для этого нужно вложить в декоратор ещё одну функцию. Например:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def decor(func):
    def vloj(a1,a2):
        a1+=5;a2+=3
        k=func(a1,a2)
        return k
    return vloj
 
@decor
def func(a1,a2):
    t=a1+a2
    return t
 
otvet=func(0,0)
print(otvet)
input()
Мы передаём func() два нуля. Однако в декораторе описана ещё одна функция vloj(), которая перехватывает аргументы, передаваемые func(), после чего происходит изменение этих самых аргументов и их перенаправление в func():

Python
1
2
a1+=5;a2+=3
k=func(a1,a2)
В общем и целом, добавить тут больше нечего. Функции, как функции, только вложены друг в друга. Главное, не забывайте, что перехват аргументов организуется за счёт вложенной в декоратор функции, а так же не пропускайте return func, ведь описать функцию - это половина дела, её ещё надо вызвать.

Кроме декораторов функций существуют ещё декораторы классов. Возьмём старый добрый класс car(), в котором на этот раз содержится только один метод - конструктор, и посредством оборачивания добавим ему два новых метода:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def decor(clas):
    class wcar():
        def __init__(self,name,age,speed):
            self.obj=clas(name,age,speed)
            self.__dict__=self.obj.__dict__
            
        def repair(self):
            self.age-=3
        def accelerate(self):
            self.speed+=20
    return wcar
 
@decor
class car:
    def __init__(self,name,age,speed):
        self.name=name
        self.age=age
        self.speed=speed
 
c=car('Audi',8,180)
Таким образом, Мы получаем класс car(), содержащий в себе не только родные методы, но и методы, описанные в декораторе. Обратите внимание на то, что структура класса усложняется: появляется объект, вложенный в другой объект в качестве параметра. Следовательно, методы описанные в оборачиваемом классе нельзя вызвать напрямую, только через этот вложенный объект. С такой же проблемой Мы столкнулись в прошлой записи. Тогда Нам удалось разрешить ситуацию, применив наследование. Здесь тот же принцип:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def decor(clas):
    class wcar(clas):
        def __init__(self,name,age,speed):
            self.obj=clas(name,age,speed)
            self.__dict__=self.obj.__dict__    
        def repair(self):
            self.age-=3
    return wcar
 
@decor
class car:
    def __init__(self,name,age,speed):
        self.name=name
        self.age=age
        self.speed=speed
    def accelerate(self):
        self.speed+=20
Классу wcar() Мы назначаем родителя: class wcar(clas):, где clas - класс car(), переданный в декоратор в качестве аргумента.
Обратите внимание на команду return wcar - эта строка возвращает объект, сконструированный по классам car() и wcar(). Если её убрать, то результатом сборки будет объект NoneType, что Нам, конечно же, не нужно.

В итоге, Мы получим класс, расширенный декоратором, но не потерявший своих былых свойств.
Как Вы уже, наверное, догадались, обёртки можно вкладывать друг в друга. Возьмём пример попроще, чтобы узреть только самую суть:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def decor1(func):
    def vloj(t):
        t=t+'Stop'
        t=func(t)
        return t
    return vloj
 
def decor2(func):
    def vloj1(t):
        t=t+' it'
        t=func(t)
        return t
    return vloj1
 
@decor1
@decor2
def func(t):
    t=t+' now!'
    return t
 
r=func('')
print(r)
Вот такой получился винегрет. Вложенная в первый декоратор функция vloj(), сделав своё дело, вызывает второй декоратор, вложенная функция vloj1() которого, обработав строку t, вызывает функцию func(), вносящую последние штрихи.

Согласитесь, даже в таком простом скрипте можно напрочь запутаться. Но не забывайте, что всегда можно написать команду: print(func), которая подскажет на какую функцию ссылается данная переменная.

Таковы основы использование декораторов. Трудно назвать их самым понятным способом решения проблем, однако и обёрткам можно найти вполне достойное применение.
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru