据我所知,@ decorator.decorator不允许在@staticmethod,@ classmethod(也许还有@property)之上进行装饰。我理解用法:
class A(object):
@classmethod
@mydecorator
def my_method(cls): pass
但是,在调试模块中,我仍然想尝试动态地执行它。所以我想知道从那些描述符(?)中检索原始方法的方法是什么。我读过很少的回复,但我还是很困惑......
我看到一个类的示例,并检索:
class my_class(property):
def __get__(self, obj, cls):
return self.fget.__get__(None, cls)
我喜欢装饰的签名保留,但仍不确定如何做到这一点。我试图实现的逻辑是:
import decorator
def mydecorator(f, *d_args, **d_kwargs):
if (isinstance(f, classmethod)):
return classmethod(mydecorator(f.__get__.?WHATELSE?))
elif (isinstance(f, staticmethod)):
return staticmethod(mydecorator(f.__get__.?WHATELSE?))
elif (isinstance(f, property)):
return property(mydecorator(f.__get__.?WHATELSE?))
else:
return decorator.decorator(f)
我正在尝试在Python 2.6中执行此操作,所以我也欢迎在未来的python版本中指出@decorator已更改(更正?)。
感谢。
答案 0 :(得分:8)
考虑到:
>>> def original():pass
>>> classmethod(original).__func__ == original
True
>>> staticmethod(original).__func__ == original
True
>>> property(original).fget == original
True
你的功能应该是这样的:
import decorator
def mydecorator(f, *d_args, **d_kwargs):
if (isinstance(f, classmethod)):
return classmethod(mydecorator(f.__func__))
elif (isinstance(f, staticmethod)):
return staticmethod(mydecorator(f.__func__))
elif (isinstance(f, property)):
return property(mydecorator(f.fget))
else:
return decorator.decorator(f)
UPD:抱歉无所事事。在2. *之前的2.7。 ,你应该这样做:
import decorator
def mydecorator(f, *d_args, **d_kwargs):
if (isinstance(f, classmethod)):
return classmethod(mydecorator(f.__get__(True).im_func))
elif (isinstance(f, staticmethod)):
return staticmethod(mydecorator(f.__get__(True)))
elif (isinstance(f, property)):
return property(mydecorator(f.fget))
else:
return decorator.decorator(f)
请注意,True
语句中的f.__get__(True).im_func
个对象可以被除None
之外的任何对象替换。
答案 1 :(得分:1)
我把它放回去,这对任何人都有用:
def redecorate(redecorator):
def wrapper(f):
info = (f, None)
if (isinstance(f, classmethod)):
info = (f.__get__(True).im_func, classmethod)
elif (isinstance(f, staticmethod)):
info = (f.__get__(True), staticmethod)
elif (isinstance(f, property)):
info = (f.fget, property)
if (info[1] is not None):
return info[1](redecorator(info[0]))
return redecorator(info[0])
return wrapper
然后,人们会这样使用它:
import decorator
@decorator.decorator
def my_decorator(f, *args, **kwargs):
print "Pre-process..."
try:
return f(*args, **kwargs)
finally:
print "Post-process..."
my_redecorator = redecorate(my_decorator)
@my_redecorator
def my_function(a): print "in my_function(a)"
class My_Class(object):
@my_redecorator
def my_method(self, a): print "in my_method(self, a)"
@my_redecorator
@classmethod
def my_classmethod1(cls, a): print "in my_classmethod1(cls, a)"
@classmethod
@my_redecorator
def my_classmethod2(cls, b): print "in my_classmethod2(cls, b)"
@my_redecorator
@staticmethod
def my_staticmethod1(a): print "in my_staticmethod1(a)"
@staticmethod
@my_redecorator
def my_staticmethod2(b): print "in my_staticmethod2(b)"
@my_redecorator
@property
def my_property1(self): print "in my_property1(self)"
@property
@my_redecorator
def my_property2(self): print "in my_property2(self)"
现在,如果我打电话给他们:
my_function(1)
My_Class.my_classmethod1(1)
My_Class.my_classmethod2(1)
My_Class.my_staticmethod1(1)
My_Class.my_staticmethod2(2)
my_class = My_Class()
my_class.my_method(1)
my_class.my_property1
my_class.my_property2
输出将是:
Pre-process...
in my_function(a)
Post-process...
Pre-process...
in my_classmethod1(cls, a)
Post-process...
Pre-process...
in my_classmethod2(cls, b)
Post-process...
Pre-process...
in my_staticmethod1(a)
Post-process...
Pre-process...
in my_staticmethod2(b)
Post-process...
Pre-process...
in my_method(self, a)
Post-process...
Pre-process...
in my_property1(self)
Post-process...
Pre-process...
in my_property2(self)
Post-process...
答案 2 :(得分:0)
我这样做的方法是将一个列表_decorated
附加到已修饰的函数中,并且能够:
def mydecorator(f): do_decoration() if hasattr(f, '_decorated'): f._decorated.append(decorator) else: f._decorated = [decorator] return f