Funktionen höherer Ordnung und Einschlussnotation in Python

Es mag besser sein, eine Frage zu stellen, aber ich möchte sie nach Bedarf hinzufügen, und ich habe das Gefühl, dass ich etwas verlieren werde, wenn es sich um eine Frage handelt, also schreibe ich sie als Artikel (egozentrisch).

Ursprünglich unter Verwendung von Schema aus verschiedenen Gründen Beschreibung von Funktionen höherer Ordnung, die aufgrund der Verwendung von Python als alternative Sprache häufig im Schema ausgedrückt werden. Ich suche nach einem Weg, um zu ersetzen In Schema werden häufig "map", "lambda" usw. verwendet, und es ist möglich, wie in Python zu schreiben, es gibt jedoch immer noch geringfügige Unterschiede, und die Notation der Listeneinschlüsse usw. wird unter dem Gesichtspunkt der Lesbarkeit und Verarbeitungsgeschwindigkeit empfohlen. Da es so scheint, möchte ich etwas tun, das durch Verständnis ausgedrückt werden kann.

In diesem Artikel werde ich die in der (?) Einschlussnotation ausgedrückte Beschreibung offenlegen und als Memorandum und Informationsaustauschmaterial verwenden. Das Schema-Verarbeitungssystem ist Gauche und das Python-Verarbeitungssystem ist Python3. Online-Programmierung /) wird vorausgesetzt.

Beschreibungsbeispiel (1) (map → Einschlussnotation)

Beschreibungsbeispiel in Schema:

(display (map + '(0 1 2 3 4) '(5 6 7 8 9)))
; => (5 7 9 11 13)

Beschreibungsbeispiel mit Pythons map und lambda:

from operator import add
print(tuple(map(add, (0,1,2,3,4), (5,6,7,8,9))))
# => (5, 7, 9, 11, 13)

Oder

print(tuple(map((lambda x, y: x + y), (0,1,2,3,4), (5,6,7,8,9))))
# => (5, 7, 9, 11, 13)

Beschreibungsbeispiel mit Python-Einschlussnotation:

print(tuple(x + y for x, y in zip((0,1,2,3,4), (5,6,7,8,9))))
# => (5, 7, 9, 11, 13)

Die Verarbeitungsgeschwindigkeit ist ... Oh, ist "map" + "add" die schnellste? Ich frage mich, ob ich einen Fehler gemacht habe (bärisch).

python


from time import time
from operator import add

R1 = range(9999999,-1,-1)
R2 = range(0,10000000)

start = time()
a = tuple(map(add, R1, R2))
print("          map + add: ", time() - start)

start = time()
b = tuple(map((lambda x,y: x + y), R1, R2))
print("       map + lambda: ", time() - start)

start = time()
c = tuple(x + y for x,y in zip(R1, R2))
print("comprehension + zip: ", time() - start)

#           map + add:  2.8753578662872314
#        map + lambda:  4.222743034362793
# comprehension + zip:  3.9112401008605957

Beschreibungsbeispiel (2) (fold /` redu``)

Beschreibungsbeispiel in Schema:

(display (fold * 1 '(1 2 3 4 5 6 7 8 9 10)))
; => 3628800

Beschreibungsbeispiel mit redu`` und lambda` von Python:

from functools import reduce
from operator import mul
print(reduce(mul, (1,2,3,4,5,6,7,8,9,10)))
# => 3628800

Oder

print(reduce(lambda x, y: x * y, (1,2,3,4,5,6,7,8,9,10)))
# => 3628800

Gibt es ein Beschreibungsbeispiel mit der Einschlussnotation von Python? Erstens ist der zu suchende Wert kein Sequenztyp, daher gibt es keine festgelegte Einbeziehung (er weicht sofort vom Zweck des Artikels ab). Es scheint, dass "Summe" als Standard für die Addition vorbereitet wird. Ist dies etwas, das Sie bei Bedarf selbst erstellen sollten (eher eine LISP-ähnliche Idee)?

def product(l):
    r = 1
    for i in l: r *= i
    return r

print(product((1,2,3,4,5,6,7,8,9,10)))
# => 3628800

Und Zeitmessung. Es ändert sich nicht viel, aber es scheint, dass "operator.mul" ein Kind sein wird, das es nicht braucht.

from functools import reduce
from time import time
from operator import mul

def product(l):
    r = 1
    for i in l: r *= i
    return r

R1 = range(1,100000)

start = time()
a = reduce(mul, R1)
print("   reduce + mul: ", time() - start)

start = time()
a = reduce(lambda x, y: x * y, R1)
print("reduce + lambda: ", time() - start)

start = time()
a = product(R1)
print("        product: ", time() - start)

#    reduce + mul:  23.096322059631348
# reduce + lambda:  18.508586406707764
#         product:  19.82227087020874

Beschreibungsbeispiel (3) (Einschlussnotation → Funktion höherer Ordnung)

Umgekehrt sollten Sie hier die folgende Beschreibung in Python-Listeneinschlussnotation mit einer Funktion höherer Ordnung ausdrücken.

python


tuple((x, y) for x in (1,2,3) for y in (7,8,9) if x + y < 11)
# => ((1, 7), (1, 8), (1, 9), (2, 7), (2, 8), (3, 7))

Für das Schema hat die erweiterte Vorschlagsspezifikation SRFI 42 eine Notation mit Listeneinschlussnotation "list-ce", die wie folgt geschrieben werden kann.

(use srfi-42)
(display (list-ec (: x '(1 2 3)) (: y '(7 8 9)) (if (< (+ x y) 11)) (list x y)))
; => ((1 7) (1 8) (1 9) (2 7) (2 8) (3 7))

Wenn Sie versuchen, dies nur mit Lambda-Ausdrücken oder "map" zu tun, wird es ziemlich kompliziert.

(display
  (filter (lambda (p) (< (+ (car p) (cadr p)) 11))
          (fold append '()
                (reverse
                  (map (lambda (x)
                         (map (lambda (y) (list x y))
                              '(7 8 9)))
                       '(1 2 3))))))
; => ((1 7) (1 8) (1 9) (2 7) (2 8) (3 7))

Der Hauptgrund ist, dass die Auswahl durch den bedingten Ausdruck durch "Filter" separat durchgeführt wird, nachdem die bedingungslose Liste einmal erzeugt wurde. Darüber hinaus verschachtelt das Verschachteln von "Karte" auch die Rückgabeliste, sodass Sie "Anhängen" durch "Falten" ("Reduzieren") reduzieren (und "Anhängen" nacheinander oben in der Liste hinzufügen müssen). Daher ist es notwendig, die Listenelemente vor dem Anhängen mit "reverse" umzukehren. Letzteres ist etwas einfacher, wenn Sie die "Append-Map" von SRFI 1 verwenden können.

(display
  (filter (lambda (p) (< (+ (car p) (cadr p)) 11))
          (append-map (lambda (x)
                        (map (lambda (y) (list x y))
                             '(7 8 9)))
                      '(1 2 3))))
; => ((1 7) (1 8) (1 9) (2 7) (2 8) (3 7))

In diesem Sinne wird, wenn die Listeneinschlussnotation nicht verwendet werden kann, "map", "fold" ("redu") und "filter" als Satz benötigt ("append" und "reverse" sind beide Listenoperationen. Diese können als typische Funktionen höherer Ordnung angesehen worden sein, als die funktionale Programmierung in Sprachen eingeführt wurde, in denen der Prozedurtyp die Hauptsprache war. Und wenn es sich um eine solche Beschreibung handelt, ist der Satzeinschluss leichter zu verstehen und wird unten weggelassen.

In Python3 ist "Reduzieren" eines der Funktionswerkzeuge der externen Bibliotheken. Da die Grundfunktion "Summe" jedoch auch Listen unterstützt, können Sie auch ohne "Reduzieren" wie folgt schreiben. Möglich.

print(
  tuple(filter(lambda p: p[0] + p[1] < 11,
               sum(tuple(map(lambda x:
                             tuple(map(lambda y: (x, y),
                                       (7,8,9))),
                             (1,2,3))),
                   ()))))
# => ((1, 7), (1, 8), (1, 9), (2, 7), (2, 8), (3, 7))

Bei Verwendung von "Reduzieren" von "Funktionswerkzeugen" ist dies wie folgt.

from functools import reduce
print(
  tuple(filter(lambda p: p[0] + p[1] < 11,
               reduce(lambda x, y: x + y,
                      tuple(map(lambda x:
                                tuple(map(lambda y: (x, y),
                                          (7,8,9))),
                                (1,2,3))),
                      ()))))
# => ((1, 7), (1, 8), (1, 9), (2, 7), (2, 8), (3, 7))

Unnötig, die Verarbeitungsgeschwindigkeit zu vergleichen. Die "Karte" erzeugt auf dem Weg viele Male "Tupel".

from time import time
from functools import reduce

N = 2000
R1 = range(1,N)

start = time()
a = tuple((x, y) for x in R1 for y in R1 if x + y < N)
print("        comprehension: ", time() - start)

start = time()
a = tuple(filter(lambda p: p[0] + p[1] < N,
               sum(tuple(map(lambda x:
                             tuple(map(lambda y: (x, y),
                                       R1)),
                             R1)),
                   ())))
print("   map + sum + filter: ", time() - start)

start = time()
a = tuple(filter(lambda p: p[0] + p[1] < N,
                 reduce(lambda x, y: x + y,
                        tuple(map(lambda x:
                                  tuple(map(lambda y: (x, y),
                                            R1)),
                                  R1)),
                        ())))
print("map + reduce + filter: ", time() - start)

#         comprehension:  0.5814449787139893
#    map + sum + filter:  27.217236757278442
# map + reduce + filter:  28.032208919525146

Beschreibungsbeispiel (4) (schnelle Sortierung)

Aus der Schlussfolgerung geht hervor, dass es keinen großen Unterschied zwischen der Listeneinschlussnotation und "Filter" + "Lambda" gibt. In dem Sinne, dass die Verarbeitung schnell ist, weil sie integriert und implementiert ist, ist die Notation der Listeneinbeziehung immer noch viel besser.

from time import time

D = range(996, -1, -1)

start = time()
def qsort1(L):
    if not L: return []
    else:
        LL = qsort1([x for x in L[1:] if x <  L[0]])
        LR = qsort1([x for x in L[1:] if x >= L[0]])
        return LL + [L[0]] + LR
a = list(qsort1(D))
print("  comprehension: ", time() - start)

start = time()
def qsort2(L):
    if not L: return []
    else:
        LL = qsort2(list(filter(lambda x: x <  L[0], L[1:])))
        LR = qsort2(list(filter(lambda x: x >= L[0], L[1:])))
        return LL + [L[0]] + LR
a = list(qsort2(D))
print("filter + lambda: ", time() - start)

#   comprehension:  0.1841585636138916
# filter + lambda:  0.3261446952819824

Bemerkungen

Änderungsprotokoll

Recommended Posts

Funktionen höherer Ordnung und Einschlussnotation in Python
Funktionen und Dekorateure höherer Ordnung
Python-Listeneinschlussnotation und Generator
Python 3 Sortier- und Vergleichsfunktionen
Python-Funktionen
Python-Tapple-Einschlüsse und Generatorausdrücke
Über Python-Diktat und sortierte Funktionen
Vergleich der Verwendung von Funktionen höherer Ordnung in Python 2 und 3
# Python-Grundlagen (Funktionen)
Python Einfach zu bedienende Funktionen
Python-Grundlagen: Funktionen
Verwenden Sie Python und MeCab mit Azure-Funktionen
Korrespondenz zwischen den in Python integrierten Funktionen und Rust
[Python] Komprimieren und dekomprimieren
Python-Anfängerhandbuch (Funktionen)
Python-Grundkurs (12 Funktionen)
Python- und Numpy-Tipps
[Python] Pip und Wheel
Python Iterator und Generator
Python-Pakete und -Module
Vue-Cli- und Python-Integration
[Python] Memo über Funktionen
Ruby, Python und Map
Python-Eingabe und Ausgabe
Python und Ruby teilen sich
Einschlussnotation in Python einrücken
# 4 [Python] Grundlagen der Funktionen
In Python integrierte Funktion ~ Zip ~
Integrierte Funktionen von Wrap Python
Python asyncio und ContextVar
Anonyme Funktion und Kartenfunktion
[Python of Hikari-] Kapitel 06-04 Funktionen (Argumente und Rückgabewerte 3)
Schreiben mit Lambda-Ausdruck und Filterfunktion und Schreiben mit Listeneinschlussnotation
[Hikari-Python] Kapitel 06-01 Funktionen (integrierte Funktionen und Funktionsdefinitionen)
[Python of Hikari-] Kapitel 06-03 Funktionen (Argumente und Rückgabewerte 2)
Curry jede Funktion mit Python ....
Programmieren mit Python und Tkinter
Python> Lambda> winzige Funktionen / Rückruffunktionen
Ver- und Entschlüsselung mit Python
Einführung in Python-Funktionen
Python: Klassen- und Instanzvariablen
3-3, Python-Zeichenfolge und Zeichencode
Python 2-Serie und 3-Serie (Anaconda Edition)
Python und Hardware-Verwenden von RS232C mit Python-
Python auf Ruby und wütend Ruby auf Python
Python-Einzug und String-Format
Python Real Number Division (/) und Integer Division (//)
Installieren Sie Python und Flask (Windows 10)
Informationen zu Python-Objekten und -Klassen
Informationen zu Python-Variablen und -Objekten
Apache mod_auth_tkt und Python AuthTkt
Lernen Sie Python-Pakete und -Module kennen
# 2 [python3] Trennung und Kommentar aus
Flache Python-Kopie und tiefe Kopie
Python und Ruby Slice Memo
Python-Installation und grundlegende Grammatik