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 .. code-block:: python 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 .. code-block:: python 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 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 .. code-block:: python 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 à .. code-block:: python 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 .. code-block:: python 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 .. code-block:: python 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 .. code-block:: python 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 .. code-block:: python 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