96

I've been looking through a tutorial and book but I can find no mention of a built in product function i.e. of the same type as sum(), but I could not find anything such as prod().

Is the only way I could find the product of items in a list by importing the mul() operator?

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
George Burrows
  • 3,391
  • 9
  • 31
  • 31
  • 8
    I came here looking for `product([1,2], [3,4]) == [(1,3), (1,4), (2,3), (2,4)]`. That one you get here: https://docs.python.org/2/library/itertools.html#itertools.product – dhill Aug 28 '15 at 14:32
  • 1
    @dhill [`itertools.product`](https://docs.python.org/2/library/itertools.html#itertools.product) is for Cartesian product of iterables. Not plain old multiplication of numbers – smci Sep 10 '18 at 10:50

4 Answers4

126

Pronouncement

Yes, that's right. Guido rejected the idea for a built-in prod() function because he thought it was rarely needed.

Python 3.8 Update

In Python 3.8, prod() was added to the math module:

>>> from math import prod
>>> prod(range(1, 11))
3628800

Alternative with reduce()

As you suggested, it is not hard to make your own using reduce() and operator.mul():

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

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

In Python 3, the reduce() function was moved to the functools module, so you would need to add:

from functools import reduce

Specific case: Factorials

As a side note, the primary motivating use case for prod() is to compute factorials. We already have support for that in the math module:

>>> import math

>>> math.factorial(10)
3628800

Alternative with logarithms

If your data consists of floats, you can compute a product using sum() with exponents and logarithms:

>>> 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
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
  • 12
    Source of the BDFL's statement: http://bugs.python.org/issue1093 – Ray Toal Oct 30 '11 at 22:23
  • 1
    Of course, `prod(range(1, 5))` is more properly written `math.factorial(4)` :) Still too bad this function isn't in the `math` module either. – Fred Foo Oct 30 '11 at 22:24
  • 5
    And of course, people who make frequent use of factorials should cache them in a list so they don't get recalculated on every call ;-) fact=[math.factorial(i) for i in range(100)] – Raymond Hettinger Oct 30 '11 at 22:29
  • 4
    @RaymondHettinger another fancy way is to use the memoize decorator on the factorial function http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize – razpeitia Oct 31 '11 at 03:42
  • 1
    Please note that reduce() has been removed from the built-in functions in python3. My answer gives alternatives for python3-users. – Paul Paulsen Jun 21 '14 at 14:34
  • 1
    I never need factorials, but I compute products from time to time. To me factorial is just a interesting programming exercise, but rarely of practical use. I guess it depends what kind of programming one does. – bli Nov 23 '17 at 10:43
  • 2
    @bli in mathematical series factorials are almost everywhere. – Yaroslav Nikitenko Aug 29 '19 at 13:38
19

There is no product in Python, but you can define it as

def product(iterable):
    return reduce(operator.mul, iterable, 1)

Or, if you have NumPy, use numpy.product.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • Damn ok thanks for the help, is it possible to define one function inside another? – George Burrows Oct 30 '11 at 22:26
  • @GeorgeBurrows: yes, you can nest function definitions, though I wouldn't do that unless you're doing higher-order stuff. – Fred Foo Oct 30 '11 at 22:27
  • 5
    Re `numpy.product`, be aware _arithmetic is modular when using integer types, and no error is raised on overflow_ [(source)](http://docs.scipy.org/doc/numpy/reference/generated/numpy.prod.html). – akxlr Jul 03 '14 at 12:14
14

Since the reduce() function has been moved to the module functools python 3.0, you have to take a different approach.

You can use functools.reduce() to access the function:

product = functools.reduce(operator.mul, iterable, 1)

Or, if you want to follow the spirit of the python-team (which removed reduce() because they think for would be more readable), do it with a loop:

product = 1
for x in iterable:
    product *= x
Paul Paulsen
  • 355
  • 4
  • 18
  • How did I not think of this ages ago? This is perfect, and Pythonic! – call-in-co Dec 28 '17 at 15:24
  • 1
    I wouldn't say that reduce() has been *removed*. It's just been moved from the list of standard functions to a module in the standard library (functools). You don't need to install anything; you'll just have to import the module. That's the same as the math library. – Bacon Bits Dec 04 '18 at 20:54
  • @BaconBits of course you are correct, thanks for pointing this out. I tried to change the wording to adress this better. – Paul Paulsen Dec 11 '18 at 21:30
9
from numpy import multiply, product
list1 = [2,2,2]
list2 = [2,2,2]
mult = 3
prod_of_lists = multiply(list1,list2)
>>>[4,4,4]
prod_of_list_by_mult = multiply(list1,mult)
>>>[6,6,6]
prod_of_single_array = product(list1)
>>>8

numpy has many really cool functions for lists!

HuntR2
  • 149
  • 4
  • 2
    I like that this answer points to a powerful numeric library — if the person asking the question really needs to do a product of a series of scalars for any reason other than homework, then the person probably needs to think about something like numbpy for the larger problem they're trying to solve. – Brandon Rhodes Oct 30 '11 at 23:48
  • 3
    I'm not sure that someone who is just starting with the Python tutorial should be pointed at numpy to solve such as simple problem. As they saying goes, "now they have two problems" :-) Once Python basics have be acquired, I do agree that numpy would we a powerful addition to the toolkit for anyone doing number crunching. – Raymond Hettinger Oct 31 '11 at 21:43