Il vaut peut-être mieux poser une question, mais j'aimerais l'ajouter au besoin, et j'ai l'impression que je vais perdre quelque chose si c'est une question, alors je l'écrirai sous forme d'article (égocentrique).
Utilisant à l'origine Scheme, pour diverses raisons Description des fonctions d'ordre supérieur souvent exprimées dans Scheme en raison de l'utilisation de Python comme langage alternatif. Je cherche un moyen de remplacer Dans Scheme, map
+ lambda
etc. sont beaucoup utilisés, et il est possible d'écrire tel quel en Python, mais il y a encore des différences subtiles, et la notation d'inclusion de liste etc. est recommandée du point de vue de la lisibilité et de la vitesse de traitement. Puisqu'il semble qu'il y en ait, j'aimerais faire quelque chose qui puisse s'exprimer par la compréhension.
Dans cet article, je vais exposer la description exprimée dans la notation d'inclusion (?) Et l'utiliser comme mémoire et matériel d'échange d'informations. Le système de traitement Scheme est Gauche et le système de traitement Python est Python3. programmation-en ligne /) est supposé.
map
→ notation d'inclusion)Exemple de description dans Scheme:
(display (map + '(0 1 2 3 4) '(5 6 7 8 9)))
; => (5 7 9 11 13)
Exemple de description utilisant map
et lambda
de Python:
+
ne peut pas être transmis directementfrom operator import add
print(tuple(map(add, (0,1,2,3,4), (5,6,7,8,9))))
# => (5, 7, 9, 11, 13)
Ou
print(tuple(map((lambda x, y: x + y), (0,1,2,3,4), (5,6,7,8,9))))
# => (5, 7, 9, 11, 13)
Exemple de description utilisant la notation d'inclusion Python:
print(tuple(x + y for x, y in zip((0,1,2,3,4), (5,6,7,8,9))))
# => (5, 7, 9, 11, 13)
La vitesse de traitement est ... Oh, est-ce que map
+ ʻadd` est le plus rapide? Je me demande si j'ai fait une erreur (baissière).
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
/ reduction
)Exemple de description dans Scheme:
(display (fold * 1 '(1 2 3 4 5 6 7 8 9 10)))
; => 3628800
Exemple de description utilisant reduction
et lambda
de Python:
from functools import reduce
from operator import mul
print(reduce(mul, (1,2,3,4,5,6,7,8,9,10)))
# => 3628800
Ou
print(reduce(lambda x, y: x * y, (1,2,3,4,5,6,7,8,9,10)))
# => 3628800
Existe-t-il un exemple de description utilisant la notation d'inclusion de Python? En premier lieu, puisque la valeur souhaitée n'est pas un type séquence, il n'y a pas d'inclusion d'ensemble (elle s'écarte immédiatement de l'objet de l'article). Il semble que «somme» soit préparée en standard pour l'addition. Est-ce quelque chose que vous devriez créer votre propre fonction si nécessaire (plutôt, une idée de type LISP)?
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
Et la mesure du temps. Cela ne change pas beaucoup, mais il semble que ʻoperator.mul` est sur le point d'être un enfant qui n'en a pas besoin.
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
Ici, à l'inverse, envisagez d'exprimer la description suivante exprimée en notation d'inclusion de liste Python avec une fonction d'ordre supérieur.
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))
En ce qui concerne Scheme, il existe une notation d'inclusion de liste "list-ce" dans la spécification de proposition étendue SRFI 42, et elle peut être écrite comme suit.
(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))
Si vous essayez de faire cela uniquement avec des expressions lambda ou map
, ce sera plutôt compliqué.
(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))
La raison principale est que la sélection par l'expression conditionnelle est effectuée par filter
séparément après avoir généré une fois la liste inconditionnelle. De plus, quand map
est imbriquée, la liste retournée est également imbriquée, donc ʻappend doit être aplati de
fold (
reduction) (et ʻappend
est ajouté en haut de la liste dans l'ordre. Par conséquent, il est nécessaire d'inverser les éléments de la liste avec «reverse» avant «append»). Ce dernier est un peu plus facile si vous pouvez utiliser ʻappend-map` de SRFI 1.
(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))
En ce sens, si la notation d'inclusion de liste ne peut pas être utilisée, map
+ fold
(reduction
) + filter
sera requis comme un ensemble (ʻappendet
reverse` sont tous deux des opérations de liste. Celles-ci peuvent avoir été considérées comme des fonctions typiques d'ordre supérieur lorsque la programmation fonctionnelle a été adoptée dans des langages dont le langage principal était procédural. Et, dans une telle description, l'inclusion d'ensemble est plus facile à comprendre et est omise ci-dessous.
En Python3, «réduire» est l'un des outils de fonction des bibliothèques externes, mais comme la fonction de base «sum» prend également en charge les listes, vous pouvez écrire comme suit même sans «réduire». Possible.
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))
Lorsque vous utilisez «réduire» des «functools», c'est comme suit.
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))
Inutile de comparer la vitesse de traitement. La «map» génère un «tuple» plusieurs fois en cours de route.
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
D'après la conclusion, il semble qu'il n'y ait pas beaucoup de différence entre la notation d'inclusion de liste et «filter» + «lambda» de manière descriptive. Dans le sens où le traitement est rapide car il est intégré et implémenté, la notation d'inclusion de liste est toujours bien meilleure.
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