2008-11-11 12 views
9

Mam raczej skomplikowany dekorator napisany przez kogoś innego. To, co chcę zrobić, to zadzwonić do dekorowanej wersji funkcji jeden raz, bazując na descision lub zadzwonić do oryginalnej funkcji (nie udekorowanej) innym razem. czy to możliwe?Python dekorowanie funkcji przed wywołaniem

Odpowiedz

26

Z:

decorator(original_function)() 

Bez:

original_function() 

dekorator jest tylko funkcja, która wykonuje funkcję jako argument i zwraca inną. Składnia @ jest całkowicie opcjonalna. Być może przesiewanie przez jakieś documentation może pomóc w wyjaśnieniu rzeczy.

+0

Link jest uszkodzony :( –

+0

Link jest naprawiony :) – chishaku

2
def original_function(): 
    pass 

decorated_function= decorator(original_function) 

if use_decorated: 
    decorated_function() 
else: 
    original_function() 

Ozdóbuj tylko raz, a następnie wybierz wersję do połączenia.

1

Oto przepis, z którym wymyśliłem problem. Musiałem również zachować podpisy tak samo, więc użyłem modułu dekoratora, ale możesz go ponownie użyć, aby tego uniknąć. Zasadniczo chodziło o to, aby dodać atrybut do funkcji. Funkcja "original" jest niezwiązana, więc jako pierwszy parametr musisz podać "self", więc dodałem do tego dodatkowy kod, żeby to sprawdzić.

# 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) 
Powiązane problemy