import functools
class Decor(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
def closure(*args, **kwargs):
print args, kwargs
return self.func(*args, **kwargs)
return closure(*args, **kwargs)
class Victim(object):
@Decor
def sum(self, a, b):
return a+b
v = Victim()
v.sum(1, 2)
Результат:
(1, 2) {}
Traceback (most recent call last):
File "test.py", line 19, in <module>
v.sum(1, 2)
File "test.py", line 11, in __call__
return closure(*args, **kwargs)
File "test.py", line 10, in closure
return self.func(*args, **kwargs)
TypeError: sum() takes exactly 3 arguments (2 given)
Как получить аргумент self
для метода?
ОБНОВЛЕНИЕ: мне удалось создать более полезную адаптацию ответа Мартейна, которая возвращает объект Decor
в ответ на __get__
, но в то же время связывает аргумент self
, когда он вызывается как метод объекта . С этой версией вы можете сказать, например. Victim.sum.hooks.append(my_favorite_function)
и my_favorite_function
будут вызываться перед Victim.sum
. ВНИМАНИЕ: эта версия небезопасна для потоков.
class Decor(object):
def __init__(self, func):
self.func = func
self.hooks = []
wraps(self.func)(self)
def __get__(self, instance, klass):
if instance != None: self.instance = instance
if klass != None: self.klass = klass
return self
def __call__(self, *args, **kwargs):
def closure(*args, **kwargs):
for function in self.hooks:
function(*args, **kwargs)
func = self.func
retval = func(*args, **kwargs) #kwargs_copy #called with notify = False
return retval
return closure.__get__(self.instance, self.klass)(*args, **kwargs)
__closure__
, но затем вызвалиclosure()
. Это опечатка? - person Martijn Pieters   schedule 21.03.2014