Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> Python

Décorateurs Python

Décorateurs Python

Un décorateur prend une fonction, ajoute des fonctionnalités et la renvoie. Dans ce didacticiel, vous apprendrez comment créer un décorateur et pourquoi vous devriez l'utiliser.

Vidéo :@Decorators en Python

Décorateurs en Python

Python a une fonctionnalité intéressante appelée décorateurs pour ajouter des fonctionnalités à un code existant.

C'est aussi appelé métaprogrammation car une partie du programme essaie de modifier une autre partie du programme au moment de la compilation.

Prérequis pour apprendre les décorateurs

Afin de comprendre les décorateurs, nous devons d'abord connaître quelques éléments de base en Python.

Nous devons être à l'aise avec le fait que tout en Python (Oui ! Même les classes), sont des objets. Les noms que nous définissons sont simplement des identifiants liés à ces objets. Les fonctions ne font pas exception, ce sont aussi des objets (avec des attributs). Plusieurs noms différents peuvent être liés au même objet fonction.

Voici un exemple.

def first(msg):
    print(msg)


first("Hello")

second = first
second("Hello")

Sortie

Hello
Hello

Lorsque vous exécutez le code, les deux fonctions first et second donner la même sortie. Ici, les noms first et second se référer au même objet fonction.

Maintenant, les choses commencent à devenir plus étranges.

Les fonctions peuvent être passées en arguments à une autre fonction.

Si vous avez utilisé des fonctions comme map , filter et reduce en Python, alors vous le savez déjà.

De telles fonctions qui prennent d'autres fonctions comme arguments sont également appelées fonctions d'ordre supérieur . Voici un exemple d'une telle fonction.

def inc(x):
    return x + 1


def dec(x):
    return x - 1


def operate(func, x):
    result = func(x)
    return result

Nous invoquons la fonction comme suit.

>>> operate(inc,3)
4
>>> operate(dec,3)
2

De plus, une fonction peut retourner une autre fonction.

def is_called():
    def is_returned():
        print("Hello")
    return is_returned


new = is_called()

# Outputs "Hello"
new()

Sortie

Hello

Ici, is_returned() est une fonction imbriquée qui est définie et renvoyée chaque fois que nous appelons is_called() .

Enfin, nous devons connaître les fermetures en Python.

Revenir aux décorateurs

Les fonctions et les méthodes sont dites appelables comme on peut les appeler.

En fait, tout objet qui implémente le spécial __call__() méthode est appelée appelable. Ainsi, dans le sens le plus élémentaire, un décorateur est un callable qui renvoie un callable.

Fondamentalement, un décorateur prend une fonction, ajoute des fonctionnalités et la renvoie.

def make_pretty(func):
    def inner():
        print("I got decorated")
        func()
    return inner


def ordinary():
    print("I am ordinary")

Lorsque vous exécutez les codes suivants dans le shell,

>>> ordinary()
I am ordinary

>>> # let's decorate this ordinary function
>>> pretty = make_pretty(ordinary)
>>> pretty()
I got decorated
I am ordinary

Dans l'exemple ci-dessus, make_pretty() est décorateur. A l'étape d'attribution :

pretty = make_pretty(ordinary)

La fonction ordinary() a été décoré et la fonction renvoyée a reçu le nom pretty .

Nous pouvons voir que la fonction de décorateur a ajouté de nouvelles fonctionnalités à la fonction d'origine. Ceci est similaire à l'emballage d'un cadeau. Le décorateur agit comme un wrapper. La nature de l'objet qui a été décoré (cadeau réel à l'intérieur) ne change pas. Mais maintenant, c'est joli (depuis qu'il a été décoré).

Généralement, nous décorons une fonction et la réattribuons comme,

ordinary = make_pretty(ordinary).

Il s'agit d'une construction courante et pour cette raison, Python a une syntaxe pour simplifier cela.

Nous pouvons utiliser le @ symbole avec le nom de la fonction décorateur et placez-le au-dessus de la définition de la fonction à décorer. Par exemple,

@make_pretty
def ordinary():
    print("I am ordinary")

est équivalent à

def ordinary():
    print("I am ordinary")
ordinary = make_pretty(ordinary)

C'est juste un sucre syntaxique pour implémenter des décorateurs.

Décorer des fonctions avec des paramètres

Le décorateur ci-dessus était simple et ne fonctionnait qu'avec des fonctions qui n'avaient aucun paramètre. Et si nous avions des fonctions qui acceptaient des paramètres comme :

def divide(a, b):
    return a/b

Cette fonction a deux paramètres, a et b . Nous savons que cela donnera une erreur si nous passons en b comme 0.

>>> divide(2,5)
0.4
>>> divide(2,0)
Traceback (most recent call last):
...
ZeroDivisionError: division by zero

Créons maintenant un décorateur pour vérifier ce cas qui causera l'erreur.

def smart_divide(func):
    def inner(a, b):
        print("I am going to divide", a, "and", b)
        if b == 0:
            print("Whoops! cannot divide")
            return

        return func(a, b)
    return inner


@smart_divide
def divide(a, b):
    print(a/b)

Cette nouvelle implémentation renverra None si la condition d'erreur se produit.

>>> divide(2,5)
I am going to divide 2 and 5
0.4

>>> divide(2,0)
I am going to divide 2 and 0
Whoops! cannot divide

De cette manière, nous pouvons décorer des fonctions qui prennent des paramètres.

Un observateur attentif remarquera que les paramètres du inner() imbriqué fonction à l'intérieur du décorateur est le même que les paramètres des fonctions qu'il décore. En tenant compte de cela, nous pouvons désormais créer des décorateurs généraux qui fonctionnent avec n'importe quel nombre de paramètres.

En Python, cette magie se fait sous la forme function(*args, **kwargs) . De cette façon, args sera le tuple des arguments positionnels et kwargs sera le dictionnaire des arguments de mots-clés. Un exemple d'un tel décorateur sera :

def works_for_all(func):
    def inner(*args, **kwargs):
        print("I can decorate any function")
        return func(*args, **kwargs)
    return inner

Chaînage des décorateurs en Python

Plusieurs décorateurs peuvent être chaînés en Python.

C'est-à-dire qu'une fonction peut être décorée plusieurs fois avec des décorateurs différents (ou identiques). Nous plaçons simplement les décorateurs au-dessus de la fonction souhaitée.

def star(func):
    def inner(*args, **kwargs):
        print("*" * 30)
        func(*args, **kwargs)
        print("*" * 30)
    return inner


def percent(func):
    def inner(*args, **kwargs):
        print("%" * 30)
        func(*args, **kwargs)
        print("%" * 30)
    return inner


@star
@percent
def printer(msg):
    print(msg)


printer("Hello")

Sortie

******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Hello
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
******************************

La syntaxe ci-dessus de,

@star
@percent
def printer(msg):
    print(msg)

est équivalent à

def printer(msg):
    print(msg)
printer = star(percent(printer))

L'ordre dans lequel nous enchaînons les décorateurs compte. Si nous avions inversé la commande comme,

@percent
@star
def printer(msg):
    print(msg)

Le résultat serait :

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
******************************
Hello
******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Python

  1. Types de données Python
  2. Opérateurs Python
  3. Instruction de passe Python
  4. Arguments de la fonction Python
  5. Fonction Python Anonyme/Lambda
  6. Fonctions Python Lambda avec EXEMPLES
  7. Fonction Python abs() :Exemples de valeurs absolues
  8. Fonction Python round() avec EXEMPLES
  9. Python range() Fonction :Float, List, For loop Exemples