Beim Erstellen von Dekoratoren für Klassenmethoden habe ich Probleme, wenn der Decorator-Mechanismus eine Klasse und keine Funktion/Schließung ist. Wenn das Klassenformular verwendet wird, wird mein Decorator nicht als gebundene Methode behandelt.Python-Dekoratoren für Klassenmitglieder schlagen fehl, wenn der Decorator-Mechanismus eine Klasse ist
Generell bevorzuge ich die Funktion Formular für Dekoratoren, aber in diesem Fall muss ich eine vorhandene Klasse verwenden, um zu implementieren, was ich brauche.
Dies scheint, als ob es mit python-decorator-makes-function-forget-that-it-belongs-to-a-class verwandt sein könnte, aber warum funktioniert es gut für die Funktionsform?
Hier ist das einfachste Beispiel, das ich machen könnte, um alles zu zeigen. Sorry über 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)
Ausgang:
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)
Ich würde empfehlen, die Frage umzubenennen. Dies bezieht sich eigentlich nicht auf Dekoratoren, sondern bezieht sich eher auf das Hinzufügen eines Funktionsobjekts als Klassenmethode. – Casebash
Im Allgemeinen (wenn auch nicht immer) kann das Problem durch Isolierung des Problems vereinfacht werden, wenn eine Frage so lang ist. Wenn Sie beispielsweise versucht hätten, die Klasse manuell mit Anmerkungen zu versehen, hätten Sie erkannt, dass sie nichts mit Dekoratoren zu tun hat, und es wäre wahrscheinlich schneller gewesen, als den gesamten Code einzugeben – Casebash