Outils pour utilisateurs

Outils du site


python:decorateurs

Décorateurs Python

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()
python/decorateurs.txt · Dernière modification : 2017/03/22 21:06 de root