Quelle est la fonction comme sum () mais pour la multiplication? produit()?


206

La sum()fonction de Python renvoie la somme des nombres dans un itérable.

sum([3,4,5]) == 3 + 4 + 5 == 12

Je recherche la fonction qui renvoie le produit à la place.

somelib.somefunc([3,4,5]) == 3 * 4 * 5 == 60

Je suis presque sûr qu'une telle fonction existe, mais je ne la trouve pas.

Réponses:


71

Mettre à jour:

Dans Python 3.8, la fonction prod a été ajoutée au module mathématique . Voir: math.prod () .

Informations plus anciennes: Python 3.7 et versions antérieures

La fonction que vous recherchez serait appelée prod () ou product () mais Python n'a pas cette fonction. Donc, vous devez écrire le vôtre (ce qui est facile).

Prononcé sur prod ()

Oui c'est vrai. Guido a rejeté l'idée d'une fonction prod () intégrée car il pensait qu'elle était rarement nécessaire.

Alternative avec réduire ()

Comme vous l'avez suggéré, il n'est pas difficile de créer le vôtre en utilisant réduire () et operator.mul () :

from functools import reduce  # Required in Python 3
def prod(iterable):
    return reduce(operator.mul, iterable, 1)

>>> prod(range(1, 5))
24

Notez que dans Python 3, la fonction Reduce () a été déplacée vers le module functools .

Cas spécifique: factorielles

En remarque, le principal cas d'utilisation motivant de prod () est de calculer les factorielles. Nous avons déjà un support pour cela dans le module mathématique :

>>> import math

>>> math.factorial(10)
3628800

Alternative avec logarithmes

Si vos données sont constituées de flottants, vous pouvez calculer un produit en utilisant sum () avec des exposants et des logarithmes:

>>> from math import log, exp

>>> data = [1.2, 1.5, 2.5, 0.9, 14.2, 3.8]
>>> exp(sum(map(log, data)))
218.53799999999993

>>> 1.2 * 1.5 * 2.5 * 0.9 * 14.2 * 3.8
218.53799999999998

Notez que l'utilisation de log () nécessite que toutes les entrées soient positives.


Vous voudrez peut-être ajouter que les flottants du dernier exemple doivent être positifs . Sinon, vous devrez peut-être utiliser cmath, mais même dans ce cas, cela ne fonctionnera pas vraiment dans tous les cas.
Veky

212

En fait, Guido a opposé son veto à l'idée: http://bugs.python.org/issue1093

Mais, comme indiqué dans ce numéro, vous pouvez en créer un assez facilement:

from functools import reduce # Valid in Python 2.6+, required in Python 3
import operator

reduce(operator.mul, (3, 4, 5), 1)

4
Voici un excellent exemple où il y a un «besoin», pour citer Guido: produit (filtre (Aucun, [1,2,3, Aucun])). J'espère que cela sera inclus un jour.
the911s

13
Guido n'est-il pas aussi le gars qui n'aime pas reduce?
Chris Martin

3
Oui - et réduire n'est même plus un module intégré dans Python 3. IMO, nous n'avons pas besoin de tous les opérateurs de liste possibles ajoutés aux modules intégrés globaux lorsqu'une bibliothèque standard (ou tierce) le ferait. Plus vous en avez, plus les mots courants deviennent interdits en tant que noms de variables locales.
ojrac

7
Je viens de trouver cette pépite dans le blog de Guido sur réduire () . "Nous avons déjà sum (); je serais heureux d'échanger des réductions () contre des produits () ..." . Si quelqu'un veut faire une demande pour l'inclusion product()dans la bibliothèque standard, le nombre de vues sur cette question peut aider à plaider la cause.
Patrick McElhaney

1
@PatrickMcElhaney Il semble que python3 se soit déjà débarrassé de la réduction intégrée. Je pense que le produit a raté sa chance. ;)
ojrac

41

Il n'y en a pas de intégré, mais il est simple de rouler le vôtre, comme illustré ici :

import operator
def prod(factors):
    return reduce(operator.mul, factors, 1)

Voir les réponses à cette question:

Quel module Python convient à la manipulation de données dans une liste?


8
Si vous utilisez Python 3, utilisez functools.reduceplutôt que reduce.
Steven Rumbalski

1
Pour encore plus d'amusement functools:prod = functools.partial(functools.reduce, operator.mul)
bukzor

39

Il y a un prod()numpy qui fait ce que vous demandez.


3
Remarque: ne prend pas en charge les longs Python (entiers de précision arbitraire), donc np.prod(range(1,13))donne la bonne réponse égale à 12! mais np.prod(range(1,14))non.
Jason S

2
@JasonS np.prod(arange(1,14, dtype='object'))?
endolith

1
La math.prod()fonction rendra cette réponse obsolète.
Benoît P

Toujours fastidieux d'avoir à importer des mathématiques lorsque vous souhaitez le faire dans une simple ligne. Il me manque réduire () et le produit rejeté par Guido ().
RCross

25
Numeric.product 

( ou

reduce(lambda x,y:x*y,[3,4,5])

)


Il veut une fonction qu'il peut charger à partir d'un module ou d'une bibliothèque, et non l'écrire lui-même.
Jeremy L

2
Mais s'il n'y en a pas, il veut probablement toujours la fonction.
DNS

1
D'accord, mais il a besoin de savoir qu'il n'en existe pas, puisque c'est sa principale question.
Jeremy L

2
Vous devez également donner à réduire une valeur par défaut de 1 sinon il échouera dans le cas nul. Le produit d'une séquence vide est défini comme 1.
Aaron Robson

3
@CraigMcQueen Numeric est (l'un des) prédécesseurs de numpy.
tacaswell

22

Utilisez ceci

def prod(iterable):
    p = 1
    for n in iterable:
        p *= n
    return p

Puisqu'il n'y a pas de prodfonction intégrée.


6
vous devez penser que réduire est vraiment un contre
modèle

1
Il voulait savoir s'il existe une fonction existante qu'il peut utiliser.
Jeremy L

Et cette réponse explique qu'il n'y en a pas.
EBGreen

5
@zweiterlinde: Pour les débutants, réduisez les risques de problèmes. Dans ce cas, en utilisant lambda a,b: a*b, ce n'est pas un problème. Mais réduire ne se généralise pas bien et est abusé. Je préfère que les débutants ne l'apprennent pas.
S.Lott

@ S.Lott Je n'ai jamais vu de débutants utiliser réduire, encore moins d'autres constructions fonctionnelles. Heck, même les programmeurs "intermédiaires" ne savent généralement pas grand-chose au-delà d'une compréhension de liste.
Mateen Ulhaq


2

Peut-être pas un "intégré", mais je le considère comme intégré. de toute façon il suffit d'utiliser numpy

import numpy 
prod_sum = numpy.prod(some_list)

C'est dangereusement proche d'une déclaration "fonctionne sur ma machine"! Numpy, si beau soit-il, n'est pas un bâti sans équivoque .
RCross
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.