LINUX.ORG.RU

Помогите въехать в декораторы

 


2

2

Капец, они меня уже достали. Это хуже, чем goto. Есть большой проект, в нем есть декоратор. Он используется в куче мест, хрен найдешь где он пределен.

И дайте годные пример этих декораторов, раз уж они есть в проекте. Читал вот это - http://habrahabr.ru/post/141411/ так и не понял нафиг оно мне надо.

Deleted

Ну насколько я понял суть декоратора: есть некая обычная функция. Если мы для нее определим декоратор, то это приведет к тому что сначала сработает декоратор и проделает некие операции, а в конце он должен вернуть функцию как результат своей работы. Вполне возможно, что декоратор в ходе своей работы поменяет свойства функции, для которой он определен. Определяет он просто как обычная функция. Примеры посмотри во flask, там, например, декоратор @route выполняет задачу подготовки функции, определенной пользователем,для обработки входящих запросов по http, проверяет что адрес запроса соответствует тому, на который он настроен. Декоратор может манипулировать объектом класса и возвращать переопределенный класс.

pylin ★★★★★
()
Последнее исправление: pylin (всего исправлений: 3)

Он используется в куче мест, хрен найдешь где он пределен.

Ну так ищи по импортам :)

так и не понял нафиг оно мне надо.

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

Hater ★★
()
Ответ на: комментарий от Deleted

Нахрена они нужны?

вынести часть кода в отдельный декоратор, который нужен для нескольких классов - вроде все ООПшненько, затем и нужны

umren ★★★★★
()
Ответ на: комментарий от Hater

Читабельность говоришь? Смотри:

# Я не знаю что это за декоратор и где он объявлен. Просто знаю что он здесь нужен
@pyqtSlot()
# Объявляю функцию обработки нажатия кнопки. Я вообще хз как декоратор связывает ее с реальной кнопкой, но оно работает
def on_testButton_clicked(self):
        QtGui.QMessageBox.question(self, u"Вопрос", u"Вы уверены?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel)

Deleted
()
Последнее исправление: Bizun (всего исправлений: 1)
Ответ на: комментарий от Deleted

В твоём конкретном случае именно так и есть. Данный декоратор превратил твой метод в слот. А описание декоратора имеет смысл поискать в pyqt.

Hater ★★
()
Ответ на: комментарий от Deleted

@pyqtSlot() # Я не знаю что это за декоратор и где он объявлен. Просто знаю что он здесь нужен
Нахрена они нужны?

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

metrokto ★★
()
Ответ на: комментарий от metrokto

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

Даже не знаю, удобно и хорошо ли это.

Deleted
()
Ответ на: комментарий от Deleted

А что он проводит с самим методом on_testButton_clicked, откуда он знает, что его надо связать с testButton?

Вангую, что по имени метода.

PolarFox ★★★★★
()
Ответ на: комментарий от Deleted

А что он проводит с самим методом on_testButton_clicked

Просто вызывает внутри себя.

откуда он знает, что его надо связать с testButton

Не знает. Выполняет свой код тогда, когда декорированный им метод вызывается.

metrokto ★★
()
Ответ на: комментарий от Deleted

Нахрена они нужны?

расширить логику базовой функции без изменения последней
а вообще да, не нужны, python и так страшен со своей мультипарадигмами

Я вообще хз

исходники pyqt4 + gdb

arrecck ★★★
()
Ответ на: комментарий от metrokto

Выполняет свой код тогда, когда декорированный им метод вызывается.

RTFM. Декоратор выполняется при объявлении.

Конструкция

@foo
def bar(): pass

Полностью аналогична

def bar(): pass
bar = foo(bar)
PolarFox ★★★★★
()
Ответ на: комментарий от Deleted

Нахрена они нужны?

Это синтаксический сахар. На самом деле ты спрашиваешь «зачем одной функции передавать аргументом другую функцию».

true_admin ★★★★★
()
Ответ на: комментарий от PolarFox

Вангую, что по имени метода.

Я тоже так думаю, да. Но я нигде не регистрировал компонент, кроме как на самой форме.

Вот, это весь код по данному компоненту:

# Ui_F003.py - файл формы
self.testButton = QtGui.QPushButton(self.grpBase)
self.testButton.setEnabled(True)
self.testButton.setObjectName(_fromUtf8("testButton"))
self.gridLayout_2.addWidget(self.testButton, 11, 0, 1, 2)

# F003Dialog.py - обработка событий формы и прочие вычисления
@pyqtSlot()
def on_testButton_clicked(self):
    QtGui.QMessageBox.question(self, u"Вопрос", u"Вы уверены?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel)

Думаю, что QPushButton таки регистрирует где то компонент, но не уверен. Если регистрирует - тогда ясно. Хотя, даже если регает, то это какой то глобальный костыль в кьюте.

П.С. maxcom питон-раскраска потекла, почини.

Deleted
()
Ответ на: комментарий от metrokto

Не знает. Выполняет свой код тогда, когда декорированный им метод вызывается.

Да, наверное так и есть. Но это не решает проблему - я ни где ни чего не регистрировал, он не мог вызвать из какого либо интересного места. Значит дело в нем.

Deleted
()
Ответ на: комментарий от Deleted

Я не знаю что это за декоратор

Погуглить не вариант? http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html#the-pyqts...

где он объявлен.

Из имени вполне понятно где он объявлен.

Просто знаю что он здесь нужен

no comments.

Я вообще хз как декоратор связывает ее с реальной кнопкой, но оно работает

В этом проблема, ты не читая доков по qt решил с головой влезть в код. Так низзя. Зная хоть немного устройство qt можно догадаться как это работает.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

ты не читая доков по qt решил с головой влезть в код. Так низзя

Ну да, а хочется!

Deleted
()

Уже сказали, что это просто такой способ вызова функций высшего порядка?

anonymous
()

Одно функция оборачивает другую. Что тут неподнятного?

fish_ka
()
Ответ на: комментарий от Deleted

Я не знаю что это за декоратор и где он объявлен. Просто знаю что он здесь нужен

Декоратор - это обычная питоновская функция, и искать где он объявлен и какую функцию он предоставляет нужно точно так же, как и для других функций и классов. Можешь, например, набрать pyqtSlot? в ipython, и оно тебе выдаст всю необходимую инфу.

provaton ★★★★★
()
Ответ на: комментарий от Deleted

Кстати, я тебя обманул. Сперва написал, потом понял.

Декоратор - это не ФВП. ФВП принимает в качестве аргумента саму функцию, а декоратор - результат ее работы. Т.е. вызов ФВП будет выглядеть вот так:

foo(func1, *argc, **argv)

а вызов декоратора - это

foo(func1(*argc, **argv), *dargc, **dargv)

Я думаю, разница понятна - в ФВП мы передаем сам объект функции (ты же уже прочитал, что в питоне все - объекты, включая функции?), а в декоратор мы передаем результат выполнения функции.

anonymous
()
Ответ на: @Class от Camel

С учетом некоторых дополнений: декоратор класса это функция, которая срабатывает при определении класса. Декоратор класса, основан на том свойстве Python, что сам класс то же объект и определением класса можно оперировать как объектом. Исходя из этого декоратор может делать нечто такое, например:

def add_field(cls):
       cls.foo = 'decorator here'

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

Как пример с SO:

class MyDecorator(object):
    def __init__(self, argument):
        self.arg = argument

    def __call__(self, fn):
        @functools.wraps(fn)
        def decorated(*args, **kwargs):
            print "In my decorator before call, with arg %s" % self.arg
            fn(*args, **kwargs)
            print "In my decorator after call, with arg %s" % self.arg
        return decorated

  

В ходе отработки данного класса как декоратора будет вызван метод __call__

pylin ★★★★★
()
Последнее исправление: pylin (всего исправлений: 4)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.