-
Можно ли с помощью декораторов добавить новые методы к классу?
Например так:
Не знаю как написать такой декоратор? (добавляет в класс method2)@add_method
class Clazz:
def method1(self, msg):
print msg
>>>c = Clazz()
>>>c.method1('ok')
ok
>>>c.method2('ok')
ok
Спасибо. -
В версии питона 2.6 можно сделать так:
Питон 2.5 не поддерживает синтаксис декорирования классов, поэтому придётся писать так:def add_method2(cls):
def method2(self):
print 'method 2'
print self.var
cls.method2 = method2
return cls
@add_method2
class Test(object):
def __init__(self):
self.var = 'instance var'
def method1(self):
print 'method 1'
>>> obj = Test()
>>> obj.method1()
>>> obj.method2()
P.S.def add_method2(cls):
def method2(self):
print 'method 2'
print self.var
cls.method2 = method2
return cls
class Test(object):
def __init__(self):
self.var = 'instance var'
def method1(self):
print 'method 1'
Test = add_method2(Test)
>>> obj = Test()
>>> obj.method1()
>>> obj.method2()
По-моему, ваш вопрос, всё же, скорее по питону в целом. А это форум о Django. -
Спасибо. Спросил в этой верке наверно по привычке.
С помощью декоратора я хочу сделать возможность вести историю по любой модели. Пока экспериментирую. -
По-моему, ваш вопрос, всё же, скорее по питону в целом. А это форум о Django.
Вроде Иван говорил про питон тоже сюда писать, чтобы отдельную ветку в форуме не заводить?... Или я отстал от жизни?
-
Вроде Иван говорил про питон тоже сюда писать, чтобы отдельную ветку в форуме не заводить?..
Может и так...
-
Я, честно говоря, сам пока не определился :-)
-
Питон 2.5 не поддерживает синтаксис декорирования классов...Вроде, это 2.3 не поддерживает короткую запись декораторов. В 2.4 и 2.5 точно есть. Есть классический пример из Learning Python - только что проверил на 2.5.1:
Собственно, выведет:class tracer:
def __init__(self, func):
self.calls = 0
self.func = func
def __call__(self, *args):
self.calls += 1
print 'call %s to %s ' % (self.calls, self.func.__name__)
self.func(*args)
@tracer
def spam(a, b, c):
print a, b, c
if __name__ == '__main__':
spam(1, 2, 3)
spam('a', 'b', 'c')
call 1 to spam
1 2 3
call 2 to spam
a b c
Иван, а может стоит завести отдельную ветку по Питону? Ну, пусть будет некоторое пересечение с веткой Django, зато удобнее модерировать. Да и найти что-то будет легче.Я, честно говоря, сам пока не определился :-) -
Вроде, это 2.3 не поддерживает короткую запись декораторов. В 2.4 и 2.5 точно есть.
Вы говорите про декораторы функций, а не классов.
Есть классический пример из Learning Python - только что проверил на 2.5.1
В вашем примере создаётся экземпляр класса tracer, вызывающий запомненную функцию в своём методе call, в то время как в исходной задаче требовалось добавить методы к самому классу.
-
В исходной задаче выявилась пакость. Если у меня в декорируемом классе уже есть method2, то он будет переопределен.
Для ведения истории я хотел переопределять save() и после его работы записывать историю, но так не прокатит.
Похоже остается только использование сигналов. -
Можно попробовать сделать вот так (для python 2.5):
def change_method1(cls):
def method1(self, possible, msg=None):
print u"Это возможно?", possible
print msg
original_method(self, possible, msg)
original_method = cls.method1
cls.method1 = method1
return cls
class Test(object):
def method1(self, possible, msg=None):
print u'Вызов старой версии метода'
Test = change_method1(Test)
if __name__ == '__main__':
obj = Test()
obj.method1(True, msg=u"Оно вам надо?") -
Вадим, а Вы не смотрели в сторону сигналов?
-
django-reversion работает как раз на сигналах
-
Вы говорите про декораторы функций, а не классов.Да, виноват — поспешил... (вокруг смех, веселье)
-
Дмитрий, я проводил испытания и выяснил что сигналы в 4-5 раз медленнее прямого выхова + каждый новый подписчик увеличивает стоимость вызова в 1.5 раза. Причем если использовать слабые ссылки connect(weak = True), то стоимость еще возрастает в 2 раза.
-
Если нужно переопределить save() для модели, то задайте в классе модели этот метод, пусть он выполняет нужные вам операции, после чего вызовите из него super(..).save(..):
super(ModelClass, self).save(force_insert, force_update)
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.






