在Python 2.5中可以用反射检查函数的装饰器吗?

2 投票
2 回答
575 浏览
提问于 2025-04-16 05:27

我想要做的是这个:

@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

撰写回答