Como posso multiplicar todos os itens de uma lista junto com o Python?

204

Preciso escrever uma função que pegue uma lista de números e os multiplique . Exemplo: [1,2,3,4,5,6]vai me dar 1*2*3*4*5*6. Eu realmente poderia usar sua ajuda.

user1897814
fonte

Respostas:

208

Python 3: use functools.reduce:

>>> from functools import reduce
>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720

Python 2: use reduce:

>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720

Para compatível com o uso 2 e 3 pip install six, então:

>>> from six.moves import reduce
>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720
nível rico
fonte
Você não importa operador, portanto, esta solução é um pouco mais compacta. Eu me pergunto o que é mais rápido.
jheld
30
@jheld: eu cronometrei a produção dos números de 1 a 100. Tanto no python2 quanto no 3, lambdalevei uma média de 0,02s / 1000 repetições, enquanto que operator.muluma média de 0,009s / 1000 repetições, tornando operator.mula ordem de magnitude mais rápida.
whereswalden
4
@wordsforthewise provavelmente é que passar por uma função extra (lambda) adiciona sobrecarga, enquanto operator.mulvai direto para C.
whereswalden
4
Eu realmente não chamaria 0,009 de uma ordem de magnitude menor que 0,02. É quase a metade.
Jlh
1
A partir do Python 3.8, isso pode ser feito simplesmente com math.prod([1,2,3,4,5,6]). (requer importação, é claro)
Tomerikoo 26/01
168

Você pode usar:

import operator
import functools
functools.reduce(operator.mul, [1,2,3,4,5,6], 1)

Veja reducee operator.muldocumentação para uma explicação.

Você precisa da import functoolslinha em Python 3+.

icecrime
fonte
32
Observe que, em python3, a reduce()função foi removida do espaço para nome global e colocada no functoolsmódulo. Então, em python3, você precisa dizer from functools import reduce.
Eugene Yarmash
2
O '1' como o terceiro argumento é desnecessário aqui, qual é o caso em que seria necessário?
wordsforthewise
5
@wordsforthewise sem o terceiro argumento, ele lança uma exceção TypeError se você passá-lo uma seqüência vazia
Francisco Couzo
1
lambda x,y: x*ytambém funciona em vez deoperator.mul
79

Eu usaria o numpy.prodpara executar a tarefa. Ver abaixo.

import numpy as np
mylist = [1, 2, 3, 4, 5, 6] 
result = np.prod(np.array(mylist))  
belindanju
fonte
13
Conveniente se você já estiver usando o Numpy. Você provavelmente não precisa mesmo de lançá-lo como uma lista em primeiro lugar, isso deve funcionar para a maioria dos casosresult = np.prod(mylist)
Nick
4
Duas coisas a serem observadas: 1) Pode estourar, especialmente se você usar o padrão numpy.int32acima. 2) Para listas pequenas, isso será significativamente mais lento, pois o NumPy precisa alocar uma matriz (relevante se repetida com frequência)
Desencantado
1
estouro para valores acima de 21 aquinp.prod(np.array(range(1,21)))
PatrickT
Não é uma boa escolha. Pode transbordar e é mais lento. tente reduce.
Peyman 31/01
57

Se você deseja evitar importar qualquer coisa e evitar áreas mais complexas do Python, pode usar um loop for simples

product = 1  # Don't use 0 here, otherwise, you'll get zero 
             # because anything times zero will be zero.
list = [1, 2, 3]
for x in list:
    product *= x
DeadChex
fonte
7
Nota secundária: As fatias no Python são muito fáceis, e como estamos lidando apenas com primitivas aqui, você pode evitar o pequeno lamento de começar com 1 iniciando com list [0] e repetindo a lista [1:]. Embora se acostumar com as respostas mais funcionais de "redução" aqui, é valioso a longo prazo, pois também é útil em outras circunstâncias.
kungphu
@kungphu O produto vazio é geralmente definida como 1, a solução seria lançar uma exceção IndexError vez disso, se você passar uma seqüência vazia
Francisco Couzo
@Francisco Concedido, mas essa função provavelmente deve gerar algum tipo de exceção nesse caso, uma vez que uma sequência vazia seria uma entrada inválida para esta função. De fato, essa função não é significativa para nenhuma sequência com menos de dois valores; se você passa uma sequência com um valor e a multiplica por 1, você basicamente adiciona um valor que não estava lá, o que eu diria que equivale a um comportamento inesperado.
Kungphu
1
@kungphu, o comportamento para esta resposta está correto, ou seja, passar uma lista de comprimento 1 retorna o valor e passar uma lista de comprimento 0 retorna 1. É na mesma linha de pensamento que dá soma ([]) como 0 ou soma ([3]) como 3. Veja: en.wikipedia.org/wiki/Empty_product
emorris
Entendo o seu ponto em relação às funções matemáticas. No entanto, em uma situação prática de desenvolvimento, eu chamaria de situação muito rara, em que uma função explicitamente destinada a operar na entrada deve retornar um valor, dado o que equivale a nenhuma entrada ou entrada inválida. Suponho que depende do objetivo do exercício: se é apenas para replicar a biblioteca padrão, OK, talvez ensine às pessoas algo sobre como a (ou a) linguagem é ou pode ser implementada. Caso contrário, eu diria que ela perde uma boa oportunidade de fornecer uma lição sobre argumentos válidos e inválidos.
precisa saber é
14

Iniciando Python 3.8, uma .prodfunção foi incluída no mathmódulo na biblioteca padrão:

math.prod(iterable, *, start=1)

O método retorna o produto de um startvalor (padrão: 1) vezes uma iterável de números:

import math
math.prod([1, 2, 3, 4, 5, 6])

>>> 720

Se o iterável estiver vazio, isso produzirá 1(ou o startvalor, se fornecido).

Xavier Guihot
fonte
10

Aqui estão algumas medidas de desempenho da minha máquina. Relevante caso isso seja realizado para pequenas entradas em um loop de longa execução:

import functools, operator, timeit
import numpy as np

def multiply_numpy(iterable):
    return np.prod(np.array(iterable))

def multiply_functools(iterable):
    return functools.reduce(operator.mul, iterable)

def multiply_manual(iterable):
    prod = 1
    for x in iterable:
        prod *= x

    return prod

sizesToTest = [5, 10, 100, 1000, 10000, 100000]

for size in sizesToTest:
    data = [1] * size

    timerNumpy = timeit.Timer(lambda: multiply_numpy(data))
    timerFunctools = timeit.Timer(lambda: multiply_functools(data))
    timerManual = timeit.Timer(lambda: multiply_manual(data))

    repeats = int(5e6 / size)
    resultNumpy = timerNumpy.timeit(repeats)
    resultFunctools = timerFunctools.timeit(repeats)
    resultManual = timerManual.timeit(repeats)
    print(f'Input size: {size:>7d} Repeats: {repeats:>8d}    Numpy: {resultNumpy:.3f}, Functools: {resultFunctools:.3f}, Manual: {resultManual:.3f}')

Resultados:

Input size:       5 Repeats:  1000000    Numpy: 4.670, Functools: 0.586, Manual: 0.459
Input size:      10 Repeats:   500000    Numpy: 2.443, Functools: 0.401, Manual: 0.321
Input size:     100 Repeats:    50000    Numpy: 0.505, Functools: 0.220, Manual: 0.197
Input size:    1000 Repeats:     5000    Numpy: 0.303, Functools: 0.207, Manual: 0.185
Input size:   10000 Repeats:      500    Numpy: 0.265, Functools: 0.194, Manual: 0.187
Input size:  100000 Repeats:       50    Numpy: 0.266, Functools: 0.198, Manual: 0.185

Você pode ver que o Numpy é um pouco mais lento em entradas menores, pois aloca um array antes da multiplicação. Além disso, preste atenção ao excesso no Numpy.

Desencantado
fonte
Você pode adicionar o caminho eval só por curiosidade
Mr_and_Mrs_D
Eu suspeito que multiply_functoolse multiply_numpy estão sob o peso de ter que procurar os np, functoolse operatorglobals, seguido por pesquisas de atributo. Você se importaria de mudar para os locais? _reduce=functools.reduce, _mul = operator.mul` na assinatura da função e depois return _reduce(_mul, iterable)no corpo, etc.
Martijn Pieters
1
Além disso, a versão numpy precisa primeiro converter os números em uma matriz numpy; você normalmente já teria feito essa conversão, para incluir isso nos horários não é realmente justo. Com a lista convertida em uma matriz numpy uma vez, a np.prod()opção inicia se torna mais rápida com 100 elementos ou mais.
Martijn Pieters
8

Pessoalmente, gosto disso para uma função que multiplica todos os elementos de uma lista genérica:

def multiply(n):
    total = 1
    for i in range(0, len(n)):
        total *= n[i]
    print total

É compacto, usa coisas simples (uma variável e um loop for) e parece intuitivo para mim (parece como eu pensaria no problema, basta pegar um, multiplicar, depois multiplicar pelo próximo, e assim por diante! )

user5038135
fonte
3
ótimo, é o mais simples e o mais simples.
ghostkraviz
4
Por que não for i in n:então total *= i? não seria muito mais simples?
Munim Munna
@MunimMunnaNão funcionou para mim da maneira acima.
athul 26/01/19
5

A maneira mais simples é:

import numpy as np
np.exp(np.log(your_array).sum())
XXinyue
fonte
10
que tal apenasnp.prod(your_Array)
traço
3

Numpytem a prod()função que retorna o produto de uma lista ou, nesse caso, como está numpy, é o produto de uma matriz em um determinado eixo:

import numpy
a = [1,2,3,4,5,6]
b = numpy.prod(a)

... ou então você pode simplesmente importar numpy.prod():

from numpy import prod
a = [1,2,3,4,5,6]
b = prod(a)
Leo Igane
fonte
2

Encontrei essa pergunta hoje, mas notei que ela não tem o caso em que há Nonena lista. Portanto, a solução completa seria:

from functools import reduce

a = [None, 1, 2, 3, None, 4]
print(reduce(lambda x, y: (x if x else 1) * (y if y else 1), a))

No caso de adição, temos:

print(reduce(lambda x, y: (x if x else 0) + (y if y else 0), a))
Xxxo
fonte
2
nums = str(tuple([1,2,3]))
mul_nums = nums.replace(',','*')
print(eval(mul_nums))
M. Dickson
fonte
5
Por favor, adicione algumas explicações à sua resposta. Como responder
xenteros 9/09/16
3
Eu grito e tento explicar o código: eu pessoalmente não gosto muito desse código, pois ele usa eval, que interpreta a string como um argumento ou função (e, portanto, geralmente é vista como algo inseguro a ser feito, especialmente ao manipular dados de entrada ) A linha anterior substitui cada vírgula delimitadora por um multiplicativo *, de modo que eval o reconheça como um multiplicativo. Eu me pergunto como o desempenho sobre isso é, especiamente em comparação com outras soluções
dennlinger
Uau, que má ideia!
Kowalski
1

Gostaria disso da seguinte maneira:

    def product_list(p):
          total =1 #critical step works for all list
          for i in p:
             total=total*i # this will ensure that each elements are multiplied by itself
          return total
   print product_list([2,3,4,2]) #should print 48
Shakti Nandan
fonte
1

Este é o meu código:

def product_list(list_of_numbers):
    xxx = 1
    for x in list_of_numbers:
        xxx = xxx*x
    return xxx

print(product_list([1,2,3,4]))

resultado: ('1 * 1 * 2 * 3 * 4', 24)

jackim
fonte
0

Que tal usar recursão?

def multiply(lst):
    if len(lst) > 1:
        return multiply(lst[:-1])* lst[-1]
    else:
        return lst[0]
mtdkki
fonte
-1

Minha solução:

def multiply(numbers):
    a = 1
    for num in numbers:
        a *= num
        return a

  pass
Dorian Vanzant
fonte
-1

'' 'o único método simples para entender o uso lógico do loop' ''

Volta = [2,5,7,7,9] x = 1 para i na Volta: x = i * x impressão (x)

Sandeep Raturi
fonte
Sua resposta não adiciona nada de novo à discussão desta pergunta.
Sid
-3

É muito simples, não importe nada. Este é o meu código. Isso definirá uma função que multiplica todos os itens de uma lista e retorna seu produto.

def myfunc(lst):
    multi=1
    for product in lst:
        multi*=product
    return product
Aditya
fonte
2
Duplicar a resposta de DeadChex, resposta de piSHOCK, resposta de Shakti Nandan. Não poste resposta já sugerida.
Munim Munna
também deve retornar multi | - |
Lars