Qual é a função como sum (), mas para multiplicação? produtos()?


206

A sum()função do Python retorna a soma dos números em um iterável.

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

Estou procurando a função que retorna o produto.

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

Tenho certeza de que essa função existe, mas não consigo encontrá-la.

Respostas:


71

Atualizar:

No Python 3.8, a função prod foi adicionada ao módulo de matemática . Veja: math.prod () .

Informações mais antigas: Python 3.7 e anterior

A função que você está procurando seria chamada prod () ou product (), mas o Python não tem essa função. Então, você precisa escrever o seu próprio (o que é fácil).

Pronunciamento sobre prod ()

Sim está certo. Guido rejeitou a ideia de uma função interna prod () porque achava que raramente era necessária.

Alternativa com reduzir ()

Como você sugeriu, não é difícil criar o seu próprio uso, reduzindo () e operator.mul () :

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

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

Observe que, no Python 3, a função reduzir () foi movida para o módulo functools .

Caso específico: fatoriais

Como uma observação lateral, o principal caso de uso motivador de prod () é calcular fatoriais. Já temos suporte para isso no módulo de matemática :

>>> import math

>>> math.factorial(10)
3628800

Alternativa com logaritmos

Se seus dados consistirem em flutuadores, você poderá calcular um produto usando sum () com expoentes e 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

Observe que o uso de log () requer que todas as entradas sejam positivas.


Você pode adicionar que os carros alegóricos no último exemplo precisam ser positivos . Caso contrário, talvez você precise usar o cmath, mas mesmo assim ele não funcionará em todos os casos.
Veky

212

Na verdade, Guido vetou a ideia: http://bugs.python.org/issue1093

Mas, como observado nessa edição, você pode criar uma facilmente:

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

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

4
Aqui está um ótimo exemplo de onde há uma "necessidade disso", para citar Guido: product (filter (None, [1,2,3, None])). Espero que seja incluído algum dia.
the911s

13
Guido também não é o cara que não gosta reduce?
Chris Martin

3
Sim - e reduzir não é mais um componente embutido no Python 3. IMO, não precisamos de todos os operadores de lista possíveis adicionados aos integrados globais quando uma biblioteca padrão (ou de terceiros) precisaria. Quanto mais integrados você tiver, mais comuns serão as palavras fora dos limites como nomes de variáveis ​​locais.
ojrac

7
Acabei de encontrar essa pepita no post de Guido no blog sobre reduzir () . "Nós já temos soma (); eu negociaria com prazer reduzir () por produto () ..." . Se alguém quiser solicitar a inclusão product()na biblioteca padrão, o número de visualizações sobre esta questão pode ajudar a defender o caso.
Patrick McElhaney

1
@PatrickMcElhaney Parece que o python3 já se livrou da redução incorporada. Eu acho que o produto perdeu sua chance. ;)
ojrac


39

Há um prod()numpy que faz o que você está pedindo.


3
nota: não suporta Python longs (números inteiros de precisão arbitrários), portanto, np.prod(range(1,13))fornece a resposta correta igual a 12! mas np.prod(range(1,14))não.
Jason S

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

1
A math.prod()função tornará esta resposta obsoleta.
Benoît P

Ainda é entediante ter que importar matemática quando quiser fazer isso de uma só vez. Sinto falta de reduzir () e do produto rejeitado por Guido ().
RCross

25
Numeric.product 

(ou

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

)


Ele quer uma função que possa carregar de um módulo ou biblioteca, não escrevendo a função.
21411 Jeremy L

2
Mas se não houver, ele provavelmente ainda quer a função.
DNS

1
Certo, mas ele precisa saber que um não existe, já que essa é sua principal questão.
21411 Jeremy L

2
Você também deve reduzir um valor padrão de 1, caso contrário, falhará no caso nulo. O produto de uma sequência de vazio é definido como 1.
Aaron Robson

3
@CraigMcQueen Numérico é (um dos) os predecessores de numpy.
tacaswell

22

Usa isto

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

Uma vez que não há prodfunção incorporada.


6
você deve pensar reduzir realmente é um antipattern :)
zweiterlinde

1
Ele queria saber se existe uma função existente que ele possa usar.
21411 Jeremy L

E esta resposta explica que não há uma.
EBGreen

5
@zweiterlinde: Para iniciantes, reduzir leva a problemas. Nesse caso, usar lambda a,b: a*bnão é um problema. Mas reduzir não generaliza bem e é abusado. Eu prefiro que iniciantes não aprendam.
315/09 S.Lott

@ S.Lott Eu nunca vi nenhum iniciante usar reduzir, muito menos quaisquer outras construções de estilo funcional. Heck, mesmo programadores "intermediários" geralmente não sabem muito além da compreensão de uma lista.
Mateen Ulhaq


2

Talvez não seja um "embutido", mas eu considero isso embutido. de qualquer forma, basta usar entorpecido

import numpy 
prod_sum = numpy.prod(some_list)

Isso é perigosamente próximo a uma declaração "funciona na minha máquina"! Numpy, por mais adorável que seja, inequivocamente, não é uma característica.
RCross
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.