¿Cuál es la función como sum () pero para la multiplicación? producto()?

206

La sum()función de Python devuelve la suma de números en un iterable.

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

Estoy buscando la función que devuelve el producto en su lugar.

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

Estoy bastante seguro de que existe tal función, pero no puedo encontrarla.

Patrick McElhaney
fuente

Respuestas:

71

Actualizar:

En Python 3.8, la función prod se agregó al módulo matemático . Ver: math.prod () .

Información anterior: Python 3.7 y anteriores

La función que está buscando se llamaría prod () o product () pero Python no tiene esa función. Entonces, necesitas escribir el tuyo (lo cual es fácil).

Pronunciamiento en prod ()

Si, eso es correcto. Guido rechazó la idea de una función prod () incorporada porque pensó que rara vez era necesaria.

Alternativa con reduce ()

Como sugirió, no es difícil hacer el suyo usando reduce () y operator.mul () :

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

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

Tenga en cuenta que en Python 3, la función reduce () se movió al módulo functools .

Caso específico: factoriales

Como nota al margen, el principal caso de uso motivador para prod () es calcular factoriales. Ya tenemos soporte para eso en el módulo de matemáticas :

>>> import math

>>> math.factorial(10)
3628800

Alternativa con logaritmos

Si sus datos consisten en flotantes, puede calcular un producto usando sum () con exponentes y logaritmos:

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

Tenga en cuenta que el uso de log () requiere que todas las entradas sean positivas.

Raymond Hettinger
fuente
Es posible que desee agregar que las carrozas en el último ejemplo deben ser positivas . De lo contrario, es posible que deba usar cmath, pero incluso así no funcionará en todos los casos.
Veky
212

En realidad, Guido vetó la idea: http://bugs.python.org/issue1093

Pero, como se señaló en ese número, puede hacer uno con bastante facilidad:

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

reduce(operator.mul, (3, 4, 5), 1)
ojrac
fuente
44
Aquí hay un gran ejemplo de dónde hay una "necesidad de esto", para citar a Guido: producto (filtro (Ninguno, [1,2,3, Ninguno])). Esperemos que sea incluido algún día.
the911s
13
¿No es Guido también el tipo al que no le gusta reduce?
Chris Martin
3
Sí, y reducir ya no es ni siquiera una función integrada en Python 3. En mi opinión, no necesitamos que todos los operadores de listas posibles se agreguen a las funciones integrales globales cuando lo haría una biblioteca estándar (o de terceros). Cuantas más incorporaciones tenga, las palabras más comunes quedarán prohibidas como nombres de variables locales.
ojrac
77
Acabo de encontrar esta pepita en la publicación de blog de Guido sobre reduce () . "Ya tenemos sum (); felizmente cambiaría reduce () por producto () ..." . Si alguien quiere solicitar su inclusión product()en la biblioteca estándar, el número de puntos de vista sobre esta pregunta puede ayudar a resolver el caso.
Patrick McElhaney
1
@PatrickMcElhaney Parece que python3 ya se deshizo de la reducción incorporada. Creo que el producto perdió su oportunidad. ;)
ojrac
41

No hay uno incorporado, pero es simple rodar el suyo, como se demuestra aquí :

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

Ver respuestas a esta pregunta:

¿Qué módulo de Python es adecuado para la manipulación de datos en una lista?

zweiterlinde
fuente
8
Si usa Python 3, use en functools.reducelugar de reduce.
Steven Rumbalski
1
Para aún más diversión functools:prod = functools.partial(functools.reduce, operator.mul)
bukzor
39

Hay una prod()en numpy que hace lo que estás pidiendo.

Benjamín
fuente
3
nota: no admite Python longs (enteros de precisión arbitraria), por lo que np.prod(range(1,13))da la respuesta correcta igual a 12 Pero np.prod(range(1,14))no lo hace.
Jason S
2
@JasonS np.prod(arange(1,14, dtype='object'))?
endolito
1
La math.prod()función hará que esta respuesta sea obsoleta.
Benoît P
Todavía es tedioso tener que importar matemáticas cuando quieres hacer esto de una manera simple. Echo de menos reduce () y el producto rechazado por Guido ().
RCross
25
Numeric.product 

(o

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

)

Steve B.
fuente
Quiere una función que pueda cargar desde un módulo o biblioteca, no escribir la función él mismo.
Jeremy L
2
Pero si no hay uno, probablemente todavía quiera la función.
DNS
1
Correcto, pero necesita saber que uno no existe, ya que esa es su pregunta principal.
Jeremy L
2
También debe reducir un valor predeterminado de 1; de lo contrario, fallará en el caso nulo. El producto de una secuencia vacía se define como 1.
Aaron Robson
3
@CraigMcQueen Numeric es (uno de) los predecesores de numpy.
tacaswell
22

Utilizar este

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

Dado que no hay una prodfunción incorporada.

S.Lott
fuente
66
debes pensar reducir realmente es un anti patrón :)
zweiterlinde
1
Quería saber si existe una función existente que pueda usar.
Jeremy L
Y esta respuesta explica que no hay una.
EBGreen
55
@zweiterlinde: Para principiantes, reduzca los cables a problemas. En este caso, usar lambda a,b: a*b, no es un problema. Pero reducir no se generaliza bien y se abusa de él. Prefiero que los principiantes no lo aprendan.
S.Lott
@ S.Lott Nunca he visto a ningún principiante usar reducir, y mucho menos cualquier otra construcción funcional. Diablos, incluso los programadores "intermedios" generalmente no saben mucho más allá de la comprensión de una lista.
Mateen Ulhaq
2

Quizás no sea un "incorporado", pero lo considero incorporado. de todos modos solo use numpy

import numpy 
prod_sum = numpy.prod(some_list)
katiex7
fuente
¡Eso está peligrosamente cerca de una declaración de "funciona en mi máquina"! Numpy, preciosa que sea, es unequivocaly no una orden interna.
RCross