[PYTHON] Fonctions et décorateurs d'ordre supérieur

Découvrez les fonctions d'ordre supérieur et la notation de décorateur de Python, qui sont des versions un peu meilleures des fonctions.

une fonction

Lorsqu'il y a un ensemble A et un ensemble B, la règle «f» qui détermine de manière unique l'élément «f (a)» de l'ensemble B pour tout élément «a» de l'ensemble A est appelée une fonction de A à B.

Considérons une fonction times2 qui double ses arguments et renvoie

def times2(i):
    return i * 2

A ce moment, si 0, 1, 2 est donné comme ʻi`,

Et une fonction de set ([0,1,2]) à un ensemble d'entiers est définie.

times2.png

Fonctions de programmation

Les fonctions ont les effets suivants en programmation:

En maîtrisant les fonctions d'ordre supérieur expliquées ci-dessous, il y a plus de situations où ces effets peuvent être obtenus.

Fonctionne comme argument

Considérez le processus consistant à appliquer la même valeur 1 aux fonctions qui multiplient l'argument par 0, multiplient par 1 et doublent les arguments.

Par rapport à la définition de la fonction times2: set ([0, 1, 2]) -> Int plus tôt, la règle de correspondance de l'ensemble des fonctions set ([times0, times1, times2]) à l'ensemble des entiers Je peux le voir.

apply1.png

ʻApply1` peut être implémenté comme suit

def apply1(f):
    return f(1)

Une fonction qui prend une fonction comme argument (ou une fonction qui renvoie une fonction comme vu dans la section suivante) est appelée une fonction d'ordre supérieur.

Fonctionne comme valeur de retour

Fonction d'ordre supérieur qui prend un nombre comme argument et renvoie une fonction

def times_n(n):
    def f(i):
        return n * i
    return f

Si vous utilisez, vous pouvez utiliser les paramètres times0, times1, times2 qui sont sortis plus tôt.

times0 = times_n(0)
times1 = times_n(1)
times2 = times_n(2)

Peut être défini comme.

times_n.png

>>> apply1(times0)
0
>>> apply1(times1)
1
>>> apply1(times2)
2

Fonctions d'un ensemble de fonctions à un ensemble de fonctions

Si vous utilisez une fonction d'ordre supérieur qui prend une fonction comme argument et renvoie la fonction

Etc. peut être écrit sous une forme réutilisable.

def dot(g):
    "f -> g . f"
    def func(f):
        def composite(i):
            return g(f(i))
        return composite
    return func
>>> (lambda i: i*2)((lambda i: i+5)(1))
12
>>> f = dot(lambda i: i*2)(lambda i: i+5)
>>> f(1)
12

Notation du décorateur

Quand il y a une fonction d'ordre supérieur décorateur qui prend une fonction comme argument et renvoie la fonction

@decorator
def function(argument):
    # ...

Remplacera «fonction» par «décorateur (fonction)».

Exemple de décorateur

Ecrivez un décorateur qui imprime un journal des appels de fonction et l'appliquez à des fonctions récursives inefficaces.

def trace(function):
    "Décorateur pour imprimer le journal des appels"
    def inner(*args):
        "Imprimer les journaux d'appels avant et après la fonction"
        print("{0}{1}".format(function.__name__, args))
        ret = function(*args)
        print("{0}{1} ==> {2}".format(function.__name__, args, ret))
        return ret
    return inner


@trace
def fib(n):
    "Trouvez le numéro de Fibonacci"
    if n == 0:
        return 0
    if n == 1:
        return 1
    return fib(n-2) + fib(n-1)

Vous pouvez voir que le même calcul a été fait plusieurs fois.

% python3 -c 'import fib; fib.fib(4)'
fib(4,)
fib(2,)
fib(0,)
fib(0,) ==> 0
fib(1,)
fib(1,) ==> 1
fib(2,) ==> 1
fib(3,)
fib(1,)
fib(1,) ==> 1
fib(2,)
fib(0,)
fib(0,) ==> 0
fib(1,)
fib(1,) ==> 1
fib(2,) ==> 1
fib(3,) ==> 2
fib(4,) ==> 3

CONSEILS: héritage des attributs

Dans l'exemple précédent, le docstirng de fib et le nom de la fonction seraient ʻinner`.

>>> fib.__doc__
'Imprimer les journaux d'appels avant et après la fonction'
>>> fib.__name__
'inner'

→ Il est douloureux d'appliquer le même décorateur à plusieurs fonctions

from functools import wraps


def trace(function):
    "Décorateur pour imprimer le journal des appels"
    @wraps(function)
    def inner(*args):
        "Imprimer les journaux d'appels avant et après la fonction"
    ...

Si tu pars

>>> fib.__doc__
'Trouvez le numéro de Fibonacci'
>>> fib.__name__
'fib'

Et hérite de la docstring et du nom de la fonction d'origine. Utile lors de l'affichage des traces de pile

CONSEILS: * args et ** kwargs

Vous pouvez écrire des décorateurs plus polyvalents en utilisant * args et ** kwargs.

CONSEILS: ne pas remplacer

Les décorateurs ne doivent pas nécessairement remplacer une fonction par une nouvelle. Par exemple

Etc. sont également possibles.

Résumé

Recommended Posts

Fonctions et décorateurs d'ordre supérieur
Fonctions d'ordre supérieur et notation d'inclusion en Python
Fonction anonyme et fonction de carte
Fonctions de tri et de comparaison Python 3
Héritage de classe et super fonction
Comparaison de l'utilisation des fonctions d'ordre supérieur dans Python 2 et 3
À propos de Python dict et des fonctions triées
Formules et fonctions (mises à jour le cas échéant)
[Python] Que sont @classmethod et les décorateurs?
GCP: fonctions de lien et Pub / Sub
Comprendre les règles et les fonctions convexes d'Armijo
Conseils pour remplacer et déboguer les fonctions
Graphiques de fonctions triangulaires avec numpy et matplotlib
Sortie du journal Google Cloud Functions (et accro)
Utiliser Python et MeCab avec Azure Functions
Correspondance entre les fonctions intégrées de Python et Rust