Décorateurs


Les décorateurs vous permettent de faire des modifications simples aux objets appelables comme fonctions, méthodes, ou classes. Nous allons nous concentrer sur les fonctions pour ce tutoriel. La syntaxe

@decorator
def functions(arg):
    return "value"

est équivalente à :

def function(arg):
    return "value"
function = decorator(function) # ceci passe la fonction au décorateur, et la réassigne à la fonction

Comme vous l'avez peut-être vu, un décorateur est juste une autre fonction qui prend une fonction et en retourne une. Par exemple, vous pourriez faire ceci :

def repeater(old_function):
    def new_function(*args, **kwds): # Voir learnpython.org/en/Multiple%20Function%20Arguments pour savoir comment *args et **kwds fonctionnent
        old_function(*args, **kwds) # nous exécutons l'ancienne fonction
        old_function(*args, **kwds) # nous la faisons deux fois
    return new_function # nous devons retourner la nouvelle fonction, sinon elle ne se réassigne pas à la valeur

Cela ferait qu'une fonction se répète deux fois.

>>> @repeater
def multiply(num1, num2):
    print(num1 * num2)

>>> multiply(2, 3)
6
6

Vous pouvez aussi faire en sorte de changer la sortie

def double_out(old_function):
    def new_function(*args, **kwds):
        return 2 * old_function(*args, **kwds) # modifier la valeur de retour
    return new_function

changer l'entrée

def double_Ii(old_function):
    def new_function(arg): # ne fonctionne que si l'ancienne fonction a un argument
        return old_function(arg * 2) # modifier l'argument passé
    return new_function

et faire des vérifications.

def check(old_function):
    def new_function(arg):
        if arg < 0: raise (ValueError, "Negative Argument") # Cela provoque une erreur, ce qui est mieux que faire la mauvaise chose
        old_function(arg)
    return new_function

Disons que vous voulez multiplier la sortie par une quantité variable. Vous pourriez définir le décorateur et l'utiliser comme suit :

def multiply(multiplier):
    def multiply_generator(old_function):
        def new_function(*args, **kwds):
            return multiplier * old_function(*args, **kwds)
        return new_function
    return multiply_generator # il retourne le nouveau générateur

# Utilisation
@multiply(3) # multiply n'est pas un générateur, mais multiply(3) l'est
def return_num(num):
    return num

# Maintenant return_num est décoré et réassigné à lui-même
return_num(5) # devrait retourner 15

Vous pouvez faire ce que vous voulez avec l'ancienne fonction, même l'ignorer complètement ! Les décorateurs avancés peuvent également manipuler la chaîne de documentation et le nombre d'arguments. Pour des décorateurs astucieux, allez sur http://wiki.python.org/moin/PythonDecoratorLibrary.

Exercice

Créez une fabrique de décorateurs qui retourne un décorateur qui décore des fonctions avec un argument. La fabrique doit prendre un argument, un type, puis retourner un décorateur qui doit vérifier si l'entrée est du bon type. Si ce n'est pas le cas, elle doit imprimer("Mauvais type") (En réalité, elle devrait lever une erreur, mais la levée d'erreur n'est pas dans ce tutoriel). Regardez le code du tutoriel et la sortie attendue pour voir ce qu'il en est si vous êtes confus (je sais que je le serais). Utiliser isinstance(object, type_of_object) ou type(object) pourrait aider.


Copyright © learnpython.org. Read our Terms of Use and Privacy Policy