226 votes

Retourner le produit d'une liste

Est-il plus concis, efficace ou simplement pythonic façon de faire les choses suivantes?

def product(list):
    p = 1
    for i in list:
        p *= i
    return p

EDIT:

Je trouve que c'est légèrement plus rapide que l'aide de l'opérateur.mul:

from operator import mul
# from functools import reduce # python3 compatibility

def with_lambda(list):
    reduce(lambda x, y: x * y, list)

def without_lambda(list):
    reduce(mul, list)

def forloop(list):
    r = 1
    for x in list:
        r *= x
    return r

import timeit

a = range(50)
b = range(1,50)#no zero
t = timeit.Timer("with_lambda(a)", "from __main__ import with_lambda,a")
print("with lambda:", t.timeit())
t = timeit.Timer("without_lambda(a)", "from __main__ import without_lambda,a")
print("without lambda:", t.timeit())
t = timeit.Timer("forloop(a)", "from __main__ import forloop,a")
print("for loop:", t.timeit())

t = timeit.Timer("with_lambda(b)", "from __main__ import with_lambda,b")
print("with lambda (no 0):", t.timeit())
t = timeit.Timer("without_lambda(b)", "from __main__ import without_lambda,b")
print("without lambda (no 0):", t.timeit())
t = timeit.Timer("forloop(b)", "from __main__ import forloop,b")
print("for loop (no 0):", t.timeit())

donne-moi

('with lambda:', 17.755449056625366)
('without lambda:', 8.2084708213806152)
('for loop:', 7.4836349487304688)
('with lambda (no 0):', 22.570688009262085)
('without lambda (no 0):', 12.472226858139038)
('for loop (no 0):', 11.04065990447998)

210voto

Ruggero Turra Points 2624

Sans l'aide de lambda:

from operator import mul
reduce(mul, list, 1)

il est mieux et plus rapide:

from operator import mul
# from functools import reduce # python3 compatibility

def with_lambda(list):
    reduce(lambda x, y: x * y, list)

def without_lambda(list):
    reduce(mul, list)

def with_numpy(list):
    np.prod(list)

import timeit

a = range(100)
t = timeit.Timer("with_lambda(a)", "from __main__ import with_lambda,a")
print("with lambda:", t.timeit())
t = timeit.Timer("without_lambda(a)", "from __main__ import without_lambda,a")
print("without lambda:", t.timeit())
t = timeit.Timer("with_numpy(a)", "from __main__ import with_numpy,a")
print("with numpy:", t.timeit())
# with numpy using native numpy array
a = np.array(a)
t = timeit.Timer("with_numpy(a)", "from __main__ import with_numpy,a")
print("with numpy using array:", t.timeit())

python 2.7.3:

with lambda: 11.967346906661987
without lambda: 4.980381011962891
with numpy: 23.889320850372314
with numpy using array: 6.758054971694946

python 3.2.3:

with lambda: 16.810785055160522
without lambda: 6.442083120346069

Python 3 plus lent?

62voto

Johannes Charra Points 6720
reduce(lambda x, y: x * y, list, 1)

53voto

Andre Holzner Points 6419

si vous avez des numéros dans votre liste:

from numpy import prod
prod(list)

19voto

Je me souviens de longues discussions sur comp.lang.python (désolé, trop paresseux pour produire des pointeurs maintenant) qui a conclu que l'original de votre product() définition est la plus Pythonic.

Notez que la proposition n'est pas d'écrire une boucle à chaque fois que vous voulez le faire, mais pour écrire une fonction qu'une seule fois (par type de réduction) et de l'appeler en tant que de besoin! L'appel de fonctions de réduction est très Pythonic - il travaille doucement avec le générateur d'expressions, et depuis le succès de l'introduction de l' sum(), Python ne cesse de croître, plus builtin fonctions de réduction - any() et all() sont les ajouts les plus récents...

Cette conclusion est un peu officiel - reduce() a été supprimé à partir d'objets internes en Python 3.0, en disant:

"Utiliser functools.reduce() si vous en avez vraiment besoin; cependant, 99% du temps explicite pour la boucle est plus lisible."

Voir aussi Le sort de réduire() en Python 3000 pour un soutien citation de Guido (et certains moins de soutien de commentaires par Lispers qui lisez ce blog).

P. S. si par hasard vous avez besoin d' product() de la combinatoire, voir math.factorial() (nouveau 2.6).

18voto

Ian Clelland Points 15066
import operator
reduce(operator.mul, list, 1)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X