Beschreibt Funktionen höherer Ordnung, bei denen es sich um eine etwas größere Version von Funktionen handelt, sowie die Dekorationsnotation von Python.
Wenn es eine Menge A und eine Menge B gibt, wird die Regel "f", die das Element "f (a)" der Menge B für jedes Element "a" der Menge A eindeutig bestimmt, als Funktion von A nach B bezeichnet.
Stellen Sie sich eine Funktion times2
vor, die ihre Argumente verdoppelt und zurückgibt
def times2(i):
return i * 2
Wenn zu diesem Zeitpunkt 0, 1, 2 als "i" angegeben wird,
times2(0) == 0
times2(1) == 2
times2(2) == 4
Und eine Funktion von set ([0,1,2])
zu einer Menge von ganzen Zahlen wird definiert.
Funktionen haben folgende Auswirkungen auf die Programmierung:
Durch Beherrschen der unten erläuterten Funktionen höherer Ordnung gibt es mehr Situationen, in denen diese Effekte erzielt werden können.
Stellen Sie sich vor, Sie wenden denselben Wert 1 auf die Funktionen an, die das Argument mit 0 multiplizieren, mit 1 multiplizieren und die Argumente verdoppeln.
times0(1) == 0
times1(1) == 1
times2(1) == 2
Verglichen mit der Definition der Funktion times2: set ([0, 1, 2]) -> Int
wird die Korrespondenzregel von der Menge der Funktionen set ([times0, times1, times2])
zur Menge der Ganzzahlen Ich kann es sehen.
apply1(times0) == 0
apply1(times1) == 1
apply1(times2) == 2
apply1
kann wie folgt implementiert werden
def apply1(f):
return f(1)
Eine Funktion, die eine Funktion als Argument verwendet (oder eine Funktion, die eine Funktion zurückgibt, wie im nächsten Abschnitt gezeigt), wird als Funktion höherer Ordnung bezeichnet.
Funktion höherer Ordnung, die eine Zahl als Argument verwendet und eine Funktion zurückgibt
def times_n(n):
def f(i):
return n * i
return f
Wenn Sie verwenden, können Sie die zuvor veröffentlichten "times0", "times1", "times2" verwenden.
times0 = times_n(0)
times1 = times_n(1)
times2 = times_n(2)
Kann definiert werden als.
>>> apply1(times0)
0
>>> apply1(times1)
1
>>> apply1(times2)
2
Wenn Sie eine Funktion höherer Ordnung verwenden, die eine Funktion als Argument verwendet und die Funktion zurückgibt
Usw. kann in wiederverwendbarer Form geschrieben werden.
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
Wenn es eine Funktion höherer Ordnung "Dekorator" gibt, die eine Funktion als Argument verwendet und die Funktion zurückgibt
@decorator
def function(argument):
# ...
Ersetzt function
durch decorator (function)
.
Schreiben Sie einen Dekorateur, der ein Protokoll von Funktionsaufrufen druckt, und wenden Sie es auf ineffiziente rekursive Funktionen an.
def trace(function):
"Dekorateur zum Drucken des Anrufprotokolls"
def inner(*args):
"Anrufprotokolle vor und nach der Funktion drucken"
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):
"Finden Sie die Fibonacci-Nummer"
if n == 0:
return 0
if n == 1:
return 1
return fib(n-2) + fib(n-1)
Sie können sehen, dass dieselbe Berechnung viele Male durchgeführt wurde.
% 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
Im vorherigen Beispiel wäre das Dokument von "fib" und der Funktionsname das von "inner".
>>> fib.__doc__
'Anrufprotokolle vor und nach der Funktion drucken'
>>> fib.__name__
'inner'
→ Es ist schmerzhaft, wenn Sie denselben Dekorateur auf mehrere Funktionen anwenden
from functools import wraps
def trace(function):
"Dekorateur zum Drucken des Anrufprotokolls"
@wraps(function)
def inner(*args):
"Anrufprotokolle vor und nach der Funktion drucken"
...
Wenn du gehst
>>> fib.__doc__
'Finden Sie die Fibonacci-Nummer'
>>> fib.__name__
'fib'
Und erbt die Dokumentzeichenfolge und den Namen der ursprünglichen Funktion. Nützlich beim Anzeigen von Stapelspuren
* args
und ** kwargs
Sie können vielseitigere Dekorateure mit * args
und ** kwargs
schreiben.
Dekorateure müssen nicht unbedingt eine Funktion durch eine neue ersetzen. Zum Beispiel
unittest.skipIf
)setattr
und gebe die ursprüngliche Funktion zurückUsw. sind ebenfalls möglich.
Recommended Posts