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.

Patrick McElhaney
fonte

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.

Raymond Hettinger
fonte
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)
ojrac
fonte
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
41

Não há um incorporado, mas é simples criar o seu, como demonstrado aqui :

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

Veja as respostas para esta pergunta:

Qual módulo Python é adequado para manipulação de dados em uma lista?

zweiterlinde
fonte
8
Se estiver usando Python 3, use em functools.reducevez de reduce.
Steven Rumbalski
1
Para ainda mais diversão com as funções:prod = functools.partial(functools.reduce, operator.mul)
bukzor
39

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

Benjamin
fonte
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])

)

Steve B.
fonte
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.

S.Lott
fonte
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)
katiex7
fonte
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