En python 3, vous pouvez juste dire @some_decorator(first_method)
, et cela fonctionnera, comme toutes les méthodes sont des fonctions normales dans les classes comme les conteneurs.
En python 2, il existe un système compliqué de & méthodes non liées, instance, classe et statiques. Pour cette raison, vous ne pouvez pas accéder à first_method
à l'intérieur d'une définition de classe m (jusqu'à ce que la classe soit complètement formée).
Une petite solution serait de diviser cette classe en deux classes:
class BaseA(object):
def first_method(self):
print "I'm the first method!"
class A(BaseA):
@some_decorator(BaseA.first_method)
def second_method(self):
print "I'm the second method!"
pas la meilleure solution pour tous les cas, mais fonctionnera.
De plus, gardez à l'esprit que dans les deux cas (py2 & AP3), le décorateur fera référence à la first_method
comme il a été déclaré ici. Si une classe descendante redéfinit la méthode, la nouvelle méthode ne sera PAS utilisée dans le décorateur; seul le parent sera utilisé.
Probablement, vous ne devriez pas du tout faire référence à first_method
. Au lieu de cela, acceptez self
/cls
premier argument de position dans l'enveloppe du décorateur, et utiliser self.first_method
/cls.first_method
il:
import functools
def some_decorator(fn):
@functools.wraps(fn)
def wrapper(self, *args, **kwargs):
first_method = self.first_method
first_method()
return fn(self, *args, **kwargs)
return wrapper
class A(object):
def first_method(self):
print "I'm the first method of A!"
@some_decorator
def second_method(self):
print "I'm the second method!"
class B(A):
def first_method(self):
print "I'm the first method of B!"
A().second_method()
# I'm the first method of A!
# I'm the second method!
B().second_method()
# I'm the first method of B!
# I'm the second method!
Si vous voulez faire cette méthode configurable:
def some_decorator(method_name):
def decorator(fn):
@functools.wraps(fn)
def wrapper(self, *args, **kwargs):
first_method = getattr(self, method_name)
first_method()
return fn(self, *args, **kwargs)
return wrapper
return decorator
class A(object):
def first_method(self):
print "I'm the first method of A!"
@some_decorator('first_method')
def second_method(self):
print "I'm the second method!"
class B(A):
def first_method(self):
print "I'm the first method of B!"
Je pense que ce post petit blog pourrait être utile: http://scottlobdell.me/2015/04/decorators-arguments-python/ – freddiev4
@ FreddieV4, je suis conscient de la façon de créer un décorateur avec des arguments. Le problème, comme indiqué, est que «A» n'est pas défini en lui-même. Le fait de référencer 'first_method' depuis' A' mais en dehors d'une fonction retournera la méthode non liée 'first_method', pas' A.first_method'. –