Python et les décorateurs¶
Un décorateur permet d’encapsuler une focntion dans une autre fonction.
Cela peut permettre d’avoir un fonctionnement similaire à un héritage mais au niveau d’une fonction.
Un exemple simple
def decorate(fn):
fn.__doc__ = 'fonction decoree %s' % fn.__doc__
return fn
@decorate
def a_function():
"""ma fonction"""
print "taitement"
print(a_function.__doc__)
retourne
fonction decoree ma fonction
On peut ainsi, par exemple, contrôler un argument sur un ensemble de fonction. dans cet exemple nous controlons que l’argument est un entier
def only_ints(fn):
def _only_ints(arg):
if not isinstance(arg,int):
raise TypeError("'%s' doit etre un entier" % str(arg))
return fn(arg)
return _only_ints
@only_ints
def b_function(arg):
return arg + 1
print(b_function(1))
print(b_function("a"))
ce qui donne
2
Traceback (most recent call last):
File "test_decoration.py", line 24, in <module>
print(b_function("a"))
File "test_decoration.py", line 15, in _only_ints
raise TypeError("'%s' doit etre un entier" % str(arg))
TypeError: 'a' doit etre un entier
il est possible de décorer la même fonction avec plusieurs décorateurs. ainsi
def decorate1(fn):
print('decorate1')
return fn
def decorate2(fn):
print('decorate2')
return fn
@decorate1
@decorate2
def c_function():
print "taitement"
print(c_function())
ce qui revient à
decorate1(decorate2(c_function))
ce qui donne
decorate1
decorate2
taitement
il est aussi possible d’imaginer une gestion de log qui contrôle le début et la fin du lancment de la fonction
def log(fn):
def _log_fn(arg):
print('%s start function' % fn.__name__)
fn_exec = fn(arg)
print('%s end function' % fn.__name__)
return fn_exec
return _log_fn
@log
def d_function(arg):
print "taitement d"
return arg
print(d_function(1))
ce qui donne
d_function start function
taitement d
d_function end function
1
un décorateur avec un paramètre
def decorateur(valeur):
def fonction_interne(fonction):
def fonction_retour():
return fonction + valeur
return fonction_retour
return fonction_interne
@decorateur("coucou")
def lm():
print "fred"
décorateur générique
def decorateur(fonction):
def fonction_interne(*args, **kwargs):
print "liste des arguments"
print "args: %s" % (args,)
print "kwargs: %s" % (kwargs,)
return fonction(*args, **kwargs)
return fonction_interne
@decorateur()
def lm(a,b):
return a+b
Pour gérer des propriétés de classe
class Mamouth(object):
_valeur = "3 calots"
@property
def valeur(self):
return self._valeur.upper()
@valeur.setter
def valeur(self, valeur):
self._valeur = valeur.strip()
>>> bille = Mamouth()
>>> bille.valeur
u'3 CALOTS'
>>> bille.valeur = "une pépite "
>>> bille.valeur
>>> print(bille.valeur)
UNE PÉPITE