7 Stimmen

Python-Dekoratoren auf Klassenmitgliedern schlagen fehl, wenn der Dekorationsmechanismus eine Klasse ist

Bei der Erstellung von Dekoratoren für die Verwendung in Klassenmethoden habe ich Probleme, wenn der Dekoratormechanismus eine Klasse und nicht eine Funktion/Schließung ist. Wenn die Klassenform verwendet wird, wird mein Dekorator nicht als gebundene Methode behandelt.

Im Allgemeinen ziehe ich es vor, die Funktionsform für Dekoratoren zu verwenden, aber in diesem Fall muss ich eine bestehende Klasse verwenden, um zu implementieren, was ich brauche.

Es scheint, als ob dies mit folgenden Faktoren zusammenhängt python-decorator-makes-function-forget-that-it-belongs-to-a-class aber warum funktioniert das bei der Funktionsform so gut?

Hier ist das einfachste Beispiel, das ich machen konnte, um alle Vorgänge zu zeigen. Entschuldigung für die Menge an Code:

def decorator1(dec_param):
    def decorator(function):
        print 'decorator1 decoratoring:', function
        def wrapper(*args):
            print 'wrapper(%s) dec_param=%s' % (args, dec_param)
            function(*args)
        return wrapper
    return decorator

class WrapperClass(object):
    def __init__(self, function, dec_param):
        print 'WrapperClass.__init__ function=%s dec_param=%s' % (function, dec_param)
        self.function = function
        self.dec_param = dec_param

    def __call__(self, *args):
        print 'WrapperClass.__call__(%s, %s) dec_param=%s' % (self, args, self.dec_param)
        self.function(*args)

def decorator2(dec_param):
    def decorator(function):
        print 'decorator2 decoratoring:', function
        return WrapperClass(function, dec_param)
    return decorator

class Test(object):
    @decorator1(dec_param=123)
    def member1(self, value=1):
        print 'Test.member1(%s, %s)' % (self, value)

    @decorator2(dec_param=456)
    def member2(self, value=2):
        print 'Test.member2(%s, %s)' % (self, value)

@decorator1(dec_param=123)
def free1(value=1):
    print 'free1(%s)' % (value)

@decorator2(dec_param=456)
def free2(value=2):
    print 'free2(%s)' % (value)

test = Test()
print '\n====member1===='
test.member1(11)

print '\n====member2===='
test.member2(22)

print '\n====free1===='
free1(11)

print '\n====free2===='
free2(22)

Ausgabe:

decorator1 decoratoring: <function member1 at 0x3aba30>
decorator2 decoratoring: <function member2 at 0x3ab8b0>
WrapperClass.__init__ function=<function member2 at 0x3ab8b0> dec_param=456
decorator1 decoratoring: <function free1 at 0x3ab9f0>
decorator2 decoratoring: <function free2 at 0x3ab970>
WrapperClass.__init__ function=<function free2 at 0x3ab970> dec_param=456

====member1====
wrapper((<__main__.Test object at 0x3af5f0>, 11)) dec_param=123
Test.member1(<__main__.Test object at 0x3af5f0>, 11)

====member2====
WrapperClass.__call__(<__main__.WrapperClass object at 0x3af590>, (22,)) dec_param=456
Test.member2(22, 2)        <<<- Badness HERE!

====free1====
wrapper((11,)) dec_param=123
free1(11)

====free2====
WrapperClass.__call__(<__main__.WrapperClass object at 0x3af630>, (22,)) dec_param=456
free2(22)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X