Fonctions d'ordre supérieur et notation d'inclusion en Python

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é.

Exemple de description (1) (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:

from 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

Exemple de description (2) (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

Exemple de description (3) (notation d'inclusion → fonction d'ordre supérieur)

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 (ʻappendetreverse` 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

Exemple de description (4) (tri rapide)

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

Remarques

Journal des modifications

Recommended Posts

Fonctions d'ordre supérieur et notation d'inclusion en Python
Fonctions et décorateurs d'ordre supérieur
Notation et générateur d'inclusion de liste Python
Fonctions de tri et de comparaison Python 3
Fonctions Python
Inclusions de tapple Python et expressions de générateur
À propos de Python dict et des fonctions triées
Comparaison de l'utilisation des fonctions d'ordre supérieur dans Python 2 et 3
# Bases de Python (fonctions)
Fonctions Python faciles à utiliser
bases de python: fonctions
Utiliser Python et MeCab avec Azure Functions
Correspondance entre les fonctions intégrées de Python et Rust
[python] Compresser et décompresser
Guide du débutant Python (fonctions)
Cours de base Python (12 fonctions)
Astuces Python et Numpy
[Python] pip et roue
Itérateur et générateur Python
Paquets et modules Python
Intégration Vue-Cli et Python
[Python] Mémo sur les fonctions
Ruby, Python et carte
entrée et sortie python
Python et Ruby se séparent
Indentation de la notation d'inclusion en Python
# 4 [python] Bases des fonctions
Fonction intégrée Python ~ Zip ~
Fonctions intégrées Wrap Python
Python asyncio et ContextVar
Fonction anonyme et fonction de carte
[Python of Hikari-] Chapitre 06-04 Fonctions (arguments et valeurs de retour 3)
Comment écrire à l'aide d'une expression lambda et d'une fonction de filtre et comment écrire à l'aide de la notation d'inclusion de liste
[Hikari-Python] Chapitre 06-01 Fonctions (fonctions intégrées et définitions de fonctions)
[Python of Hikari-] Chapitre 06-03 Fonctions (arguments et valeurs de retour 2)
Curry n'importe quelle fonction avec Python ...
Programmation avec Python et Tkinter
Python> lambda> petites fonctions / fonctions de rappel
Chiffrement et déchiffrement avec Python
Introduction aux fonctions Python
Python: variables de classe et d'instance
3-3, chaîne Python et code de caractère
Série Python 2 et série 3 (édition Anaconda)
Python et matériel - Utilisation de RS232C avec Python -
Python sur Ruby et Ruby en colère sur Python
Indentation Python et format de chaîne
division des nombres réels python (/) et division des nombres entiers (//)
Installez Python et Flask (Windows 10)
À propos des objets et des classes Python
À propos des variables et des objets Python
Apache mod_auth_tkt et Python AuthTkt
Apprenez à connaître les packages et les modules Python
# 2 [python3] Séparation et commentaire
Copie superficielle Python et copie profonde
Mémo tranche python et rubis
Installation de Python et grammaire de base