Come posso moltiplicare tutti gli elementi in un elenco insieme a Python?


204

Devo scrivere una funzione che prende un elenco di numeri e li moltiplica insieme. Esempio: [1,2,3,4,5,6]mi darà 1*2*3*4*5*6. Potrei davvero usare il tuo aiuto.

Risposte:


208

Python 3: usa functools.reduce:

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

Python 2: usa reduce:

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

Per l'uso compatibile con 2 e 3 pip install six, quindi:

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

Non importare operatore, quindi questa soluzione è un po 'più compatta. Mi chiedo quale sia più veloce.
tenuto il

30
@jheld: ho cronometrato producendo i numeri da 1 a 100. In entrambi python2 e 3, ho lambdapreso una media di 0,02 ripetizioni / 1000 ripetizioni, mentre operator.mulho preso una media di 0,009s / 1000 ripetizioni, rendendo operator.mulun ordine di grandezza più veloce.
whereeswalden

4
@wordsforthewise probabilmente è che passare attraverso una funzione extra (lambda) aggiunge spese generali, mentre operator.mulva direttamente a C.
whereeswalden

4
Non chiamerei davvero .009 un ordine di grandezza inferiore a .02. È solo circa la metà.
jlh

1
A partire da Python 3.8, può essere semplicemente fatto con math.prod([1,2,3,4,5,6]). (richiede ovviamente l'importazione)
Tomerikoo,

168

Puoi usare:

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

Vedi reducee operator.muldocumentazione per una spiegazione.

Hai bisogno della import functoolslinea in Python 3+.


32
Si noti che in python3, la reduce()funzione è stata rimossa dallo spazio dei nomi globale e collocata nel functoolsmodulo. Quindi in python3 devi dire from functools import reduce.
Eugene Yarmash,

2
L'1 come terzo argomento non è necessario qui, qual è il caso in cui sarebbe necessario?
parole per il

5
@wordsforthewise senza il terzo argomento, genera un'eccezione TypeError se si passa una sequenza vuota
Francisco Couzo,

1
lambda x,y: x*yfunziona anche al posto dioperator.mul

79

Vorrei utilizzare il numpy.prodper eseguire l'attività. Vedi sotto.

import numpy as np
mylist = [1, 2, 3, 4, 5, 6] 
result = np.prod(np.array(mylist))  

13
Conveniente se stai già utilizzando Numpy. Probabilmente non hai nemmeno bisogno di lanciarlo prima come elenco, questo dovrebbe funzionare per la maggior parte dei casiresult = np.prod(mylist)
Nick,

4
Due cose a cui prestare attenzione: 1) Potrebbe traboccare, soprattutto se si utilizza l'impostazione predefinita numpy.int32come sopra 2) Per elenchi di piccole dimensioni questo sarà significativamente più lento, poiché NumPy deve allocare un array (rilevante se ripetuto spesso)
Disincantato

1
overflow per valori superiori a 21 quinp.prod(np.array(range(1,21)))
PatrickT

Non è una buona scelta. Può traboccare ed è più lento. provare reduce.
Peyman,

57

Se vuoi evitare di importare qualcosa ed evitare aree più complesse di Python, puoi usare un semplice ciclo per

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

7
Nota minore: le fette in Python sono molto semplici e poiché trattiamo solo di primitive qui, puoi evitare il piccolo problema di iniziare con 1 iniziando con list [0] e ripetendo list [1:]. Anche se sentirsi a proprio agio con le risposte "riduci" più funzionali qui è utile a lungo termine poiché è utile anche in altre circostanze.
Kungphu,

@kungphu Il prodotto vuoto viene generalmente definito come 1, la soluzione genererebbe invece un'eccezione IndexError se si passa una sequenza vuota
Francisco Couzo,

@Francisco Concesso, ma questa funzione probabilmente dovrebbe generare qualche tipo di eccezione in quel caso, poiché una sequenza vuota sarebbe un input non valido per questa funzione. In effetti, questa funzione non è significativa per nessuna sequenza con meno di due valori; se passi una sequenza con un valore e lo moltiplichi per 1, hai essenzialmente aggiunto un valore che non c'era, il che direi equivale a un comportamento imprevisto.
Kungphu,

1
@kungphu, il comportamento di questa risposta è corretto, ovvero passare un elenco di lunghezza 1 restituisce il valore e passare un elenco di lunghezza 0 restituisce 1. È nella stessa linea di pensiero che dà sum ([]) come 0 o sum ([3]) as 3. Vedi: en.wikipedia.org/wiki/Empty_product
emorris

Vedo il tuo punto riguardo alle funzioni matematiche. Tuttavia, in una situazione di sviluppo pratico, la definirei una situazione molto rara in cui una funzione che è esplicitamente progettata per operare sull'input dovrebbe restituire un valore dato ciò che equivale a nessun input o input non valido. Suppongo che dipenda dall'obiettivo dell'esercizio: se si tratta solo di replicare la libreria standard, OK, forse insegna alla gente qualcosa su come (o a) il linguaggio è o può essere implementato. Altrimenti direi che manca una buona opportunità per fornire una lezione su argomenti validi e non validi.
Kungphu,

14

A partire Python 3.8, una .prodfunzione è stata inclusa nel mathmodulo nella libreria standard:

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

Il metodo restituisce il prodotto di un startvalore (valore predefinito: 1) volte un iterabile di numeri:

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

>>> 720

Se l'iterabile è vuoto, questo produrrà 1(o il startvalore, se fornito).


10

Ecco alcune misurazioni delle prestazioni dalla mia macchina. Rilevante nel caso in cui ciò venga eseguito per piccoli input in un ciclo di lunga durata:

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}')

risultati:

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

Puoi vedere che Numpy è un po 'più lento su input più piccoli, poiché alloca un array prima che venga eseguita la moltiplicazione. Inoltre, fai attenzione al trabocco di Numpy.


Potresti aggiungere la via del giudizio solo per curiosità
Mr_and_Mrs_D

Lo sospetto multiply_functoolse multiply_numpy sono appesantito dal dover guardare in alto np, functoolse operatorglobalmente, seguito da ricerche di attributi. Ti dispiacerebbe passare alla gente del posto? _reduce=functools.reduce, _mul = operator.mul` nella firma della funzione quindi return _reduce(_mul, iterable)nel corpo, ecc.
Martijn Pieters

1
Inoltre, la versione numpy deve prima convertire i numeri in un array numpy; normalmente avresti già effettuato quella conversione, includerlo nei tempi non è proprio giusto. Con l'elenco convertito in una matrice numpy una volta, l' np.prod()opzione inizia diventa più veloce con almeno 100 elementi.
Martijn Pieters

8

Personalmente mi piace questo per una funzione che moltiplica tutti gli elementi di un elenco generico insieme:

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

È compatto, usa cose semplici (una variabile e un ciclo for) e mi sembra intuitivo (sembra come penso al problema, ne prendo uno, lo moltiplico, poi lo moltiplico per il successivo e così via! )


3
fantastico, è il più semplice e il più semplice.
ghostkraviz,

4
Perché no for i in n:, allora total *= i? non sarebbe molto più semplice?
Munim Munna,

@MunimMunnaNon ha funzionato per me come sopra.
Atene,


3

Numpyha la prod()funzione che restituisce il prodotto di un elenco, o in questo caso poiché è intorpidito, è il prodotto di un array su un determinato asse:

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

... oppure puoi semplicemente importare numpy.prod():

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

2

Ho trovato questa domanda oggi, ma ho notato che non ha il caso in cui ci siano Nonenell'elenco. Quindi, la soluzione completa sarebbe:

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

In caso di aggiunta, abbiamo:

print(reduce(lambda x, y: (x if x else 0) + (y if y else 0), a))

2
nums = str(tuple([1,2,3]))
mul_nums = nums.replace(',','*')
print(eval(mul_nums))

5
Aggiungi una spiegazione alla tua risposta. Come rispondere
xenteros

3
Mi chino e cerco di spiegare il codice: personalmente questo codice non mi piace molto, dal momento che usa eval, che interpreta la stringa come argomento o funzione (ed è quindi generalmente visto come una cosa non sicura da fare, specialmente quando si gestiscono i dati di input ). La riga prima sostituisce ogni virgola delimitante con un moltiplicativo *, in modo tale che eval lo riconosca come moltiplicativo. Mi chiedo come siano le prestazioni, soprattutto rispetto ad altre soluzioni
Dennlinger

Caspita, che brutta idea!
Kowalski,

1

Vorrei questo nel modo seguente:

    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

1

Questo è il mio codice:

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

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


0

Che ne dici di usare la ricorsione?

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

-1

La mia soluzione:

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

  pass

-1

'' 'l'unico metodo semplice per comprendere l'uso della logica per il loop' ''

Giro = [2,5,7,7,9] x = 1 per i nel giro: x = i * x stampa (x)


La tua risposta non aggiunge nulla di nuovo alla discussione di questa domanda.
Sid,

-3

È molto semplice non importare nulla. Questo è il mio codice Ciò definirà una funzione che moltiplica tutti gli articoli in un elenco e restituisce il loro prodotto.

def myfunc(lst):
    multi=1
    for product in lst:
        multi*=product
    return product

2
Duplica alla risposta di DeadChex, la risposta di piSHOCK, la risposta di Shakti Nandan. Non pubblicare risposte già suggerite.
Munim Munna,

dovrebbe anche restituire multi | - |
Lars
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.