Heim > Artikel > Backend-Entwicklung > [Python] Ein erster Blick auf „Funktionale Programmierung“
Letztes Semester habe ich einen Kurs namens „Künstliche Intelligenz“ besucht. Der Lehrer hat uns gezwungen, eine Sprache namens Prolog zu lernen Wir haben vorher gelernt, dass mein Leben anders war. Ich habe lange darüber nachgedacht, den Turm von Hanoi zu schreiben, und habe ihn schließlich geändert (aus Angst, vom Lehrer entdeckt zu werden). Bevor ich es geschrieben habe, habe ich einen Absatz gepostet, um ein Gefühl dafür zu bekommen:
hanoi(N) :- dohanoi(N, 'a', 'b', 'c'). dohanoi(0, _ , _ , _ ) :- !. dohanoi(N, A, B, C) :- N1 is N-1, dohanoi(N1, A, C, B), writeln([move, N, A-->C]), dohanoi(N1, B, A, C).
Damals habe ich es fast verstanden, aber der Hauptgrund war, dass es zu wenig Informationen gab und das Debuggen nicht möglich war Frage: Immer wenn ich auf einen Fehler stoße, wird mir immer wieder schwindelig. Es wird jedoch gesagt, dass Prolog damals mit Lisp konkurrieren konnte, und ich habe mich in letzter Zeit ein wenig für Lisp interessiert. Nachdem ich diese Dinge abgeschlossen habe, werde ich dieser Art von funktionaler Sprache meine Hommage erweisen.
Was ist funktionale Programmierung? Liao Da schrieb hier:
Funktionale Programmierung ist ein Programmierparadigma mit einem hohen Abstraktionsgrad. Daher gibt es für jede Funktion keine Variablen Die Eingabe ist bestimmt, die Ausgabe ist bestimmt. Wir nennen diese reine Funktion ohne Nebenwirkungen. In Programmiersprachen, die die Verwendung von Variablen zulassen, kann die gleiche Eingabe zu unterschiedlichen Ausgaben führen, da der Variablenstatus innerhalb der Funktion ungewiss ist. Daher hat diese Art von Funktion Nebenwirkungen.
Vielleicht haben Sie es nach dem Lesen immer noch nicht verstanden. Machen Sie sich keine Sorgen, lesen Sie zuerst diese Abschnitte.
In der Mathematik und Informatik ist eine Funktion höherer Ordnung eine Funktion, die mindestens eine der folgenden Bedingungen erfüllt:
Akzeptiert eine oder mehrere A-Funktionen als Eingabe
und gibt eine Funktion aus
Das heißt, die Funktion selbst wird als Parameter übergeben. oder eine Funktion zurückgeben.
Zum Beispiel können Sie einer Variablen wie eine normale Zuweisung eine Funktion zuweisen:
>>> min(1, 2) 1 >>> f = min >>> f(1, 2) 1 >>> f <built-in function min> >>> min <built-in function min>
Sie können einer Funktion auch einen Wert zuweisen (Fortsetzung des Codes):
>>> min = 10 >>> min(1, 2) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not callable >>> f(1, 2) 1 >>> min = f >>> min(1, 2) 1
Okay, übergeben Sie Parameter, zum Beispiel eine Funktion, die die Summe aller Zahlen berechnet:
>>> def add(a, b): ... return a+b ... >>> def mysum(f, *l): ... a = 0 ... for i in l: ... a = f(a, i) ... return a ... >>> mysum(add, 1, 2, 3) 6 >>> mysum(add, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 55
Natürlich bedeutet das Ersetzen dieses f durch Multiplikation, dass das Produkt aller Zahlen berechnet wird.
Werfen wir einen Blick auf einige der in Python integrierten Funktionen höherer Ordnung, die häufig verwendet werden.
Ich erinnere mich vage, dass ich dieses Wort letztes Semester gehört habe, als ich einen Cloud-Computing-Kurs belegte, aber der Kurs war sehr langweilig, also habe ich ihm anscheinend nicht viel zugehört Es seltsam zu finden, wenn ich es hier sehe. ?
Aber es gibt nicht viel zu sagen. Lassen Sie uns kurz über die Rolle der einzelnen Funktionen sprechen.
Für die Karte sieht die Berechnungsformel wie folgt aus:
map(f, [x1, x2, ..., xn]) = [f(x1), f(x2), ..., f(xn)]
Für die Reduzierung sieht die Berechnungsformel wie folgt aus:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
Liao Dana sagte Sehr klar.
Filter ähnelt der Kartenfunktion, akzeptiert eine Funktion und ist iterierbar und gibt eine Liste zurück. Seine Funktion besteht jedoch darin, zu bestimmen, ob der Wert beibehalten werden soll, basierend darauf, ob die Funktion einen Wert zurückgibt ist wahr. Zum Beispiel:
def is_odd(n): return n % 2 == 1 list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) # 结果: [1, 5, 9, 15]
Die sortierte Funktion ist auch eine Funktion höherer Ordnung. Durch Übergeben der Funktion an den Parameter Schlüssel kann die zu sortierende Reihenfolge über die Schlüsselfunktion verarbeitet werden Sortieren Sie es, aber es wird den Wert der Sequenz nicht ändern, zum Beispiel:
>>> sorted([36, 5, -12, 9, -21], key=abs) [5, 9, -12, -21, 36]
Ich werde nicht über anonyme Funktionen sprechen, ich werde eine nehmen Wenn ich sie später verwende, schaue ich mir den Dekorator schon lange an, also werde ich ihn mir noch einmal ansehen.
Der erste ist ein einfacher Dekorator, der das Protokoll vor jedem Funktionsaufruf ausdruckt:
import logging def log(func): def wrapper(*args, **kw): logging.warn("%s is running" % func.__name__) func(*args, **kw) return wrapper
Dies ist ein äußerst einfacher Dekorator, wie man ihn verwendet ? Die erste Verwendung, die ich gesehen habe, bestand darin, @ vor der Funktion hinzuzufügen, die dekoriert werden muss, aber tatsächlich ist dies ein syntaktischer Zucker von Python. Die ursprünglichste Verwendung ist verständlicher. Definieren Sie zuerst eine Funktion f:
def f(): print("in function f") f = log(f)
Nach dieser Definition rufen wir die f-Funktion auf:
>>> f() WARNING:root:f is running in function f
Das Ergebnis der Verwendung von @log ist das gleiche. Tatsächlich dient das @-Symbol als syntaktischer Zucker für den Dekorateur und hat dieselbe Funktion wie die vorherige Zuweisungsanweisung, wodurch der Code prägnanter und klarer aussieht und eine weitere Zuweisungsoperation wie die folgende vermieden wird:
@log def f(): print("in function f")
Manchmal müssen wir auch Parameter übergeben der Dekorator Um Parameter wie Status, Ebene und andere Informationen einzugeben, müssen Sie lediglich eine Funktionsschicht außerhalb der Wrapper-Funktion „umschließen“, wie unten gezeigt:
import logging def log(level): def decorator(func): def wrapper(*args, **kw): logging.warn("%s is running at level %d" % (func.__name__, level)) return func(*args, **kw) return wrapper return decorator @log(2) def f(): print("in function f") >>> f() WARNING:root:f is running at level 2 in function f
Um Decorator besser zu verstehen, können wir das Namensattribut der Funktion f ausdrucken:
#对于不加装饰器的 f,其 name 不变 >>> def f(): ... print("in function f") ... >>> f.__name__ 'f' #对于添加装饰器的函数,其 name 改变了 >>> @log ... def f(): ... print("in function f") ... >>> f.__name__ 'wrapper'
Anhand der ersten Zuweisungsanweisung des Decorators können wir grob verstehen, was passiert ist: f = log(f)
macht f Punkt to log( Der Rückgabewert von f) ist die Wrapper-Funktion. Jedes Mal, wenn die ursprüngliche Funktion f ausgeführt wird, wird die Wrapper-Funktion aufgerufen. In unserem Beispiel wird zuerst das Protokoll gedruckt und dann die ursprüngliche Funktion f ausgeführt.
Dabei gibt es jedoch ein Problem. Dadurch werden die Metainformationen der ursprünglichen Funktion f ersetzt und viele Informationen über f verschwinden. Dies ist schwer zu akzeptieren, aber glücklicherweise haben wir das functools-Modul. Ändern Die Funktion ist:
import functools import logging def log(func): functools.wraps(func) def wrapper(*args, **kw): logging.warn("%s is running" % func.__name__) func(*args, **kw) return wrapper >>> @log ... def f(): ... print("in function f") ... >>> f.__name__ 'f'
Außerdem können Sie mehrere Dekoratoren zur gleichen Funktion hinzufügen:
@a @b @c def f (): # 等价于 f = a(b(c(f)))
Ich bin nicht sehr Wenn Sie mit der funktionalen Programmierung vertraut sind, erhalten Sie hier nur ein kurzes Verständnis des Konzepts. Normalerweise ist es definitiv sinnvoller, imperative Programmierung zu verwenden. Es gibt jedoch rein funktionale Sprachen wie Haskell oder Lisp, und das Erlernen dieser Sprachen eröffnet eine neue Denkweise.
Weitere [Python]-Artikel zum Thema „Funktionale Programmierung“ finden Sie auf der chinesischen PHP-Website!