Si vous n'avez pas de problème à utiliser des arguments nommés, j'ai créé quelque chose de similaire à ce dont vous avez besoin :
def cached_property(method=None, get_attribute=lambda a: '_%s_cached' % (a,)):
"""
Met en cache l'attribut d'un objet.
Peut être utilisé sous les formes suivantes :
@cached_property
@cached_property()
@cached_property(get_attribute=lambda x: 'bla')
@param method: la méthode à mettre en mémoire
@param get_attribute: une fonction appelable qui devrait retourner l'attribut mis en cache
@return une méthode mise en mémoire
"""
def decorator(method):
def wrap(self):
private_attribute = get_attribute(method.__name__)
try:
return getattr(self, private_attribute)
except AttributeError:
setattr(self, private_attribute, method(self))
return getattr(self, private_attribute)
return property(wrap)
if method:
# Il s'agissait d'un appel de décorateur réel, par exemple : @cached_property
return decorator(method)
else:
# Il s'agit d'un appel d'usine, par exemple : @cached_property()
return decorator
Cela fonctionne parce qu'un seul argument sans mot-clé, la fonction décorée, est passé au décorateur.
Remarquez que j'ai également utilisé les arguments passés à la fonction décorée, dans ce cas 'self'.