====== Décorateurs Python ======
Source : http://gillesfabio.com/blog/2010/12/16/python-et-les-decorateurs/
===== Built-in decorator =====
* **@property** : transforme une fonction en propriété (en gros transforme une fonctionne comme une variable)
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class myclass(object):
x = 0
def __init__(self):
print('init')
self.x = 0
# Methode classique. Ne peux pas être appelée sans être instanciée
# myclass().foo(1)
# myclass.foo(1) >>> Erreur
def foo(self, x):
print("Executing foo ({} : {})".format(self, x))
self.x+=x
# Pas besoin d'instancier la classe pour l'appeler. A accès aux attributs de la classe qui ne commencent pas par self. A accès aux méthodes qui ne sont pas instanciées (c'est à dire aux methodes qui n'ont pas de self => @classmethod et @staticmethod).
# myclass().class_foo(1) >>> Appelle __init__ car on a instancié la classe
# myclass.class_foo(1)
@classmethod
def class_foo(cls, x):
print("Executing class_foo ({} : {})".format(cls, x))
cls.x+=x
cls.static_foo(1)
# Pas besoin d'instancier la classe pour l'appeler. Vu comme une simple fonction. N'a pas accès aux méthodes
# myclass().static_foo(1) >>> Appelle __init__ car on a instancié la classe
# myclass.static_foo(1)
@staticmethod
def static_foo(x):
print("Executing static_foo ({})".format(x))
x+=1
if __name__ == '__main__':
a=myclass()
print('x = {}'.format(a.x))
a.foo(1)
print('x = {}'.format(a.x))
a.class_foo(1)
print('x = {}'.format(a.x))
a.static_foo(1)
print('x = {}'.format(a.x))
print('*'*10)
try:
myclass.foo(1)
except Exception as e:
print(e)
myclass.class_foo(1)
myclass.static_foo(1)
===== Sans arguments =====
def decorate(func):
def wrapper(*args, **kwargs):
# Pré-traitement
response = func(*args, **kwargs)
# Post-traitement
return response
wrapper.__doc__ = func.__doc__
wrapper.__name__ = func.__name__
return wrapper
Exemple :
# -*- coding: utf-8 -*-
# Notre décorateur
def decorate(func):
print u"Je suis dans la fonction 'decorate' et je décore '%s.'" % func.__name__
def wrapper(*args, **kwargs):
print u"Je suis dans la fonction 'wrapper' qui accède aux arguments de '%s'." % func.__name__
a = list(args)
a.reverse()
print u"J'en donne la preuve, je peux les inverser : %s." % ', '.join(a)
print u"Exécution de la fonction '%s'." % func.__name__
response = func(*args)
print u"Je peux effectuer, ici, un post-traitement."
return response
return wrapper
# Notre fonction décorée
@decorate
def foobar(*args):
print ", ".join(args)
# Appel de la fonction
foobar("A", "B", "C", "D")
===== Avec arguments =====
def decorate(arg1, arg2, arg3):
def decorated(func):
def wrapper(*args, **kwargs):
# Pré-traitement
response = func(*args, **kwargs)
# Post-traitement
return response
return wrapper
return decorated
def decorate(arg1='default', arg2=None, arg3=None):
def decorated(func):
def wrapper(*args, **kwargs):
# Pré-traitement
response = func(*args, **kwargs)
# Post-traitement
return response
return wrapper
return decorated
@decorate(arg1='my value')
def foobar():
pass
# MAUVAIS
@decorate
def foobar():
pass
# BON
@decorate()
def foobar():
pass
Exemple :
# -*- coding: utf-8 -*-
def decorate(arg1, arg2, arg3):
print u'Je suis dans la fonction "decorate".'
def decorated(func):
print u'Je suis dans la fonction "decorated".'
def wrapper(*args, **kwargs):
print u'Je suis dans la fonction "wrapper".'
print u"Les arguments du décorateurs sont : %s, %s, %s." % (arg1, arg2, arg3)
print u"Pré-traitement."
print u"Exécution de la fonction %s." % func.__name__
response = func(*args, **kwargs)
print u"Post-traitement."
return response
return wrapper
return decorated
@decorate("Arg 1", "Arg 2", "Arg 3")
def foobar():
print u"Je suis foobar, je vous reçois 5 sur 5."
foobar()