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.
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`,
times2(0) == 0
times2(1) == 2
times2(2) == 4
Et une fonction de set ([0,1,2])
à un ensemble d'entiers est définie.
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.
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.
times0(1) == 0
times1(1) == 1
times2(1) == 2
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(times0) == 0
apply1(times1) == 1
apply1(times2) == 2
ʻ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.
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.
>>> apply1(times0)
0
>>> apply1(times1)
1
>>> apply1(times2)
2
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
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)».
fonction = décorateur (fonction)
après avoir défini fonction
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
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
* args
et ** kwargs
Vous pouvez écrire des décorateurs plus polyvalents en utilisant * args
et ** kwargs
.
Les décorateurs ne doivent pas nécessairement remplacer une fonction par une nouvelle. Par exemple
setattr
et retourne la fonction d'origineEtc. sont également possibles.
Recommended Posts