I need to write a function that takes
a list of numbers and multiplies them together. Example:
[1,2,3,4,5,6]
will give me 1*2*3*4*5*6
. I could really use your help.
16 Answers
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
For compatible with 2 and 3 use pip install six
, then:
>>> from six.moves import reduce
>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720
You can use:
import operator
import functools
functools.reduce(operator.mul, [1,2,3,4,5,6], 1)
See reduce
and operator.mul
documentations for an explanation.
You need the import functools
line in Python 3+.
Starting Python 3.8
, a .prod
function has been included to the math
module in the standard library:
math.prod(iterable, *, start=1)
The method returns the product of a start
value (default: 1) times an iterable of numbers:
import math
math.prod([1, 2, 3, 4, 5, 6])
>>> 720
If the iterable is empty, this will produce 1
(or the start
value, if provided).
Here's some performance measurements from my machine. Relevant in case this is performed for small inputs in a long-running loop:
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}')
Results:
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
You can see that Numpy is quite a bit slower on smaller inputs, since it allocates an array before multiplication is performed. Also, watch out for the overflow in Numpy.
I personally like this for a function that multiplies all elements of a generic list together:
def multiply(n):
total = 1
for i in range(0, len(n)):
total *= n[i]
print total
It's compact, uses simple things (a variable and a for loop), and feels intuitive to me (it looks like how I'd think of the problem, just take one, multiply it, then multiply by the next, and so on!)
Found this question today but I noticed that it does not have the case where there are None
's in the list. So, the complete solution would be:
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 the case of addition, we have:
print(reduce(lambda x, y: (x if x else 0) + (y if y else 0), a))