2008-11-11 17 views
9

Başkaları tarafından yazılmış oldukça karmaşık bir dekoratörüm var. Yapmak istediğim şey, bir defaya mahsus bir fonksiyona göre dekore edilmiş bir versiyonu çağırmak veya özgün bir işlevi (başka bir şekilde dekore edilmemiş) başka bir zamana çağırmaktır. Mümkün mü?Python işlevlerini çağırmadan önce arama fonksiyonları

decorator(original_function)() 

olmadan: ile

cevap

26

original_function() 

bir dekoratör sadece parametre olarak bir işlev alır ve başka bir döndüren bir fonksiyonudur. @ Sözdizimi tamamen isteğe bağlıdır. Belki de documentation arasındaki bir incelik, bazı şeyleri açıklığa kavuşturmaya yardımcı olabilir.

+0

Bağlantı bozuk :( –

+0

Bağlantı düzeltildi :) – chishaku

2
def original_function(): 
    pass 

decorated_function= decorator(original_function) 

if use_decorated: 
    decorated_function() 
else: 
    original_function() 

Sadece bir kez süsleyin ve sonra hangi sürümü çağırmak istediğinizi seçin.

1

İşte sorun için hazırladığım tarif. İmzaları aynı şekilde tutmam gerekiyordu, bu yüzden dekoratör modülünü kullandım ama bunu önlemek için yeniden jig yapabiliyordunuz. Temel olarak, hile, işleve bir özellik eklemekti. 'Orjinal' işlev bağlanmamış olduğundan, ilk parametrede bir 'ben' kelimesini geçmeniz gerekir, bu yüzden bunu kontrol etmek için fazladan bir kod ekledim.

# 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) 
İlgili konular