是否可以使用反射来检查Python 2.5中函数的装饰器?

时间:2010-10-14 01:06:37

标签: python

这就是我想要做的事情:

@MyDecorator
def f():
   pass

for d in f.decorators:
   print d

2 个答案:

答案 0 :(得分: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

基本上,所有装饰器都像往常一样包装函数,然后在包装器函数上放置一个decorators属性。然后它检查包装函数是否有类似的列表并向上传播。

虽然

这是无用的

我想要的是

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

答案 1 :(得分:1)

@MyDecorator语法只是编写以下Python代码的简写:

def f():
  pass
f = MyDecorator(f)

以这种形式编写,您可以看到应用于该函数的装饰器不会以任何方式跟踪。你可以让你的装饰者在他们被应用时记住(Aaron's answer有一些关于如何做到这一点的好主意),但是你必须用你自己的所有第三方装饰者包装