Repository with sources and generator of https://larlet.fr/david/ https://larlet.fr/david/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

article.md 4.1KB

title: Benchmarks map, filter vs. list-comprehensions slug: benchmarks-map-filter-vs-list-comprehensions date: 2006-10-25 19:00:06 type: post vignette: images/logos/seb_sauvage.png contextual_title1: Bonnes pratiques et astuces Python contextual_url1: 20080511-bonnes-pratiques-et-astuces-python contextual_title2: Python : lisibilité vs simplicité contextual_url2: 20060425-python-et-underscore contextual_title3: Principales nouveautés dans Python 2.5 contextual_url3: 20060304-principales-nouveautes-dans-python-25

Je viens de tomber sur les snyppets de Seb Sauvage (site que j'apprécie beaucoup par ailleurs) et il y a une phrase qui m'a interpellé sur le paragraphe consacré à zip, map, filter et aux list-comprehensions :

Except that {map|filter} is faster. (than list-comprehensions)

Ni une, ni deux, je récupère l'article de Tarek qui est très bon et qui comporte une fonction testant la durée d'execution des fonctions pour pouvoir comparer. J'avais déjà essayé d'autres fonctions mais autant innover un peu.

Allons-y donc avec le décorateur suivant :

from test import pystone
import time

kPs = 1000
TOLERANCE = 0.5 * kPs

def mesure_pystone():
    pystone.pystones(loops=pystone.LOOPS)
    pystone.pystones(loops=pystone.LOOPS)
    return pystone.pystones(loops=pystone.LOOPS)

def timedtest(function, local_pystones=mesure_pystone()):
    """ Decorator to measure execution time in pystones """
    def wrapper(*args, **kw):
        all = []
        for i in range(3):
            start_time = time.time()
            try:
                res = function(*args, **kw)
            finally:
                total_time = time.time() - start_time
                if total_time == 0:
                    temps = 0
                else:
                    ratio = local_pystones[0] / local_pystones[1]
                    temps = total_time / ratio
                all.append(temps)
        print '%d pystones' % min(all)
        return res
    return wrapper

J'ai testé les fonctions suivantes qui ne sont pas les mêmes que les exemples de Seb mais qui retournent (elles, merci Haypo :-)) le même résultat :

@timedtest
def map_without_list_comprehension():
    for i in range(10000):
        map(abs, [-5,7,-12])

@timedtest
def map_with_list_comprehension():
    for i in range(10000):
        [abs(i) for i in [-5,7,-12]]

print '=== map vs. list-comprehension ==='
print 'map without list-comprehension:'
map_without_list_comprehension()
print 'map with list-comprehension:'
map_with_list_comprehension()

@timedtest
def filter_without_list_comprehension():
    for i in range(10000):
        filter(abs, [-5,7,0,-12] )

@timedtest
def filter_with_list_comprehension():
    for i in range(10000):
        [i for i in [-5,7,0,-12] if i]

print '=== filter vs. list-comprehension ==='
print 'filter without list-comprehension:'
filter_without_list_comprehension()
print 'filter with list-comprehension:'
filter_with_list_comprehension()

Et voila les résultats obtenus :

=== map vs. list-comprehension ===
map without list-comprehension:
638 pystones
map with list-comprehension:
534 pystones
=== filter vs. list-comprehension ===
filter without list-comprehension:
612 pystones
filter with list-comprehension:
550 pystones

Il me semble que c'est sans appel : les list-comprehensions sont toujours plus rapides que map ou filter avec Python 2.4. Il faudrait tester tout ça avec Python 2.5 mais je pense que les résultats seraient encore plus significatifs.