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.
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
:
+
nicht direkt übergeben werden kann.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
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:
*
nicht direkt übergeben werden kann, wird Folgendes weggelassen.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
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
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
Recommended Posts