在Python 2.5中可以用反射检查函数的装饰器吗?
我想要做的是这个:
@MyDecorator
def f():
pass
for d in f.decorators:
print d
2 个回答
1
@MyDecorator
这种写法其实是用来简化写 Python 代码的一种方式,下面的代码就是它的完整写法:
def f():
pass
f = MyDecorator(f)
用这种方式写出来,你会发现其实并没有记录下应用到函数上的装饰器。你可以让你的装饰器记住它们是怎么被应用的,(Aaron 的回答里有一些不错的想法),不过那样的话你就得把所有第三方的装饰器都用你自己的装饰器包裹起来。
3
这通常是不可行的,除非装饰器之间能够合作。举个例子,
def my_decorator(f):
def wrapper(*args, **kwargs):
return f(*args, **kwargs)
wrapper.decorators = [wrapper]
if hasattr(f, 'decorators'):
wrapper.decorators.extend[f.decorators]
return wrapper
其实,装饰器的作用就是像往常一样包裹函数,然后在这个包裹的函数上加一个装饰器属性。接着,它会检查被包裹的函数,看是否有类似的列表,并将其向上传播。
不过,这样做其实没什么用。
我觉得你想要的是
def my_decorator(f):
def wrapper(args):
return f(args)
wrapper.decorated = f
return wrapper
这样你就可以做一些事情,比如
@my_other_decorator # another decorator following the same pattern
@my_decorator
def foo(args):
print args
foo.decorated(args) # calls the function with the inner decorated function (my_decorator)
foo.decorated.decorated(args) # original function
你实际上可以把这个模式抽象成一个装饰器。
def reversable(decorator):
def wrapper(func):
ret = decorator(func) # manually apply the decorator
ret.decorated = func # save the original function
return ret
return wrapper
现在,当你在写你的装饰器时:
@reversable
def my_decorator(f):
def wrapper(x):
return f(x + 1)
return wrapper