2008-11-11 88 views
9

我有一个由别人编写的相当复杂的装饰器。我想要做的是根据一个决定调用一次函数的装饰版本,或者再次调用原始函数(未装饰)。这可能吗?调用之前的Python装饰函数

回答

26

随着:

decorator(original_function)() 

无:

original_function() 

装饰器仅仅是一个函数,它接受一个函数作为参数并返回另一个。 @语法完全是可选的。也许筛选一些documentation可能有助于澄清事情。

+0

链接损坏:( – 2015-09-19 14:48:01

2
def original_function(): 
    pass 

decorated_function= decorator(original_function) 

if use_decorated: 
    decorated_function() 
else: 
    original_function() 

只装饰一次,然后选择要调用的版本。

1

这里是我提出的问题的食谱。我还需要保持签名相同,所以我使用了装饰模块,但是您可以重新夹紧以避免这种情况。基本上,诀窍是给函数添加一个属性。 '原始'函数没有绑定,所以你需要传入一个'self'作为第一个参数,所以我添加了一些额外的代码来检查。

# http://www.phyast.pitt.edu/~micheles/python/decorator-2.0.1.zip 
from decorator import decorator, update_wrapper 

class mustbe : pass 

def wrapper (interface_) : 
    print "inside hhh" 
    def call (func, self, *args, **kwargs) : 
     print "decorated" 
     print "calling %s.%s with args %s, %s" % (self, func.__name__, args, kwargs) 
     return interface_ (self, *args, **kwargs) 
    def original (instance , *args, **kwargs) : 
     if not isinstance (instance, mustbe) : 
      raise TypeError, "Only use this decorator on children of mustbe" 
     return interface_ (instance, *args, **kwargs) 
    call = decorator (call, interface_) 
    call.original = update_wrapper (original, call) 
    return call 

class CCC (mustbe): 
    var = "class var" 
    @wrapper 
    def foo (self, param) : 
     """foo""" 
     print self.var, param 

class SSS (CCC) : 
    @wrapper (hidden_=True) 
    def bar (self, a, b, c) : 
    print a, b, c 

if __name__ == "__main__" : 
    from inspect import getargspec 

    print ">>> i=CCC()" 
    i=CCC() 

    print ">>> i.var = 'parrot'" 
    i.var = 'parrot' 

    print ">>> i.foo.__doc__" 
    print i.foo.__doc__ 

    print ">>> getargspec(i.foo)" 
    print getargspec(i.foo) 

    print ">>> i.foo(99)" 
    i.foo(99) 

    print ">>> i.foo.original.__doc__" 
    print i.foo.original.__doc__ 

    print ">>> getargspec(i.foo.original)" 
    print getargspec(i.foo.original) 

    print ">>> i.foo.original(i,42)" 
    i.foo.original(i,42) 

    print ">>> j=SSS()" 
    j=SSS() 

    print ">>> j.bar(1,2,3)" 
    j.bar(1,2,3)