Что такое функция, как sum (), но для умножения? товар()?


206

sum()Функция Python возвращает сумму чисел в итерируемом.

sum([3,4,5]) == 3 + 4 + 5 == 12

Я ищу функцию, которая возвращает продукт вместо этого.

somelib.somefunc([3,4,5]) == 3 * 4 * 5 == 60

Я почти уверен, что такая функция существует, но я не могу ее найти.

Ответы:


71

Обновить:

В Python 3.8 функция prod была добавлена ​​в математический модуль. Смотрите: math.prod () .

Более старая информация: Python 3.7 и более ранние

Функция, которую вы ищете, будет называться prod () или product (), но Python не имеет этой функции. Итак, вам нужно написать свой собственный (что легко).

Произношение на прод ()

Да это правильно. Гвидо отверг идею встроенной функции prod (), потому что он думал, что она редко нужна.

Альтернатива с помощью Reduce ()

Как вы и предлагали, не сложно сделать свой собственный, используя redu () и operator.mul () :

from functools import reduce  # Required in Python 3
def prod(iterable):
    return reduce(operator.mul, iterable, 1)

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

Обратите внимание, что в Python 3 функция redu () была перемещена в модуль functools .

Особый случай: Факториалы

В качестве примечания, основной мотивирующий вариант использования функции prod () - вычисление факториалов. У нас уже есть поддержка для этого в математическом модуле :

>>> import math

>>> math.factorial(10)
3628800

Альтернатива с логарифмами

Если ваши данные состоят из чисел с плавающей точкой, вы можете вычислить продукт, используя sum () с показателями и логарифмами:

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

Обратите внимание, использование log () требует, чтобы все входы были положительными.


Вы можете добавить, что значения с плавающей точкой в ​​последнем примере должны быть положительными . В противном случае вам, возможно, придется использовать cmath, но даже тогда он не будет работать во всех случаях.
Veky

212

На самом деле Гвидо наложил вето на эту идею: http://bugs.python.org/issue1093

Но, как отмечено в этом выпуске, вы можете сделать это довольно легко:

from functools import reduce # Valid in Python 2.6+, required in Python 3
import operator

reduce(operator.mul, (3, 4, 5), 1)

4
Вот отличный пример того, где есть «необходимость в этом», чтобы процитировать Guido: product (filter (None, [1,2,3, None])). Надеюсь, он будет включен когда-нибудь.
911-е

13
Разве Гвидо не тот парень, который не любит reduce?
Крис Мартин

3
Да - и Reduce больше не является даже встроенной в Python 3. ИМО, нам не нужно, чтобы все возможные операторы списков добавлялись в глобальные встроенные функции, когда это делает стандартная (или сторонняя) библиотека. Чем больше у вас встроенных функций, тем более распространенные слова становятся запрещенными в качестве имен локальных переменных.
ojrac

7
Только что нашёл этот самородок в посте Гвидо о редукторе () . Msgstr "У нас уже есть sum (); я бы с удовольствием обменял Reduce () на product () ..." . Если кто-то хочет подать ходатайство о включении product()в стандартную библиотеку, количество просмотров по этому вопросу может помочь в обосновании.
Патрик МакЭлхани

1
@PatrickMcElhaney Звучит так, будто python3 уже избавился от встроенной функции Reduce. Я думаю, что продукт упустил свой шанс. ;)
ojrac

41

Там нет ни одного встроенного, но его просто свернуть, как показано здесь :

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

Смотрите ответы на этот вопрос:

Какой модуль Python подходит для обработки данных в списке?


8
Если вы используете Python 3, используйте functools.reduceвместо reduce.
Стивен Румбальски

1
Для еще большего удовольствия prod = functools.partial(functools.reduce, operator.mul)
functools

39

Там prod()в NumPy, который делает то, что вы просите.


3
примечание: не поддерживает длинные значения Python (произвольные целые числа точности), поэтому np.prod(range(1,13))дает правильный ответ, равный 12! но np.prod(range(1,14))нет.
Джейсон С

2
@JasonS np.prod(arange(1,14, dtype='object'))?
Эндолит

1
math.prod()Функция сделает этот ответ устаревшим.
Бенуа П

По-прежнему утомительно импортировать математику, когда вы хотите сделать это в простой однострочной. Я скучаю по Reduce () и отклоненному Guido продукту ().
RCross

25
Numeric.product 

( или

reduce(lambda x,y:x*y,[3,4,5])

)


Он хочет функцию, которую он может загрузить из модуля или библиотеки, а не сам писать функцию.
Джереми Л

2
Но если его нет, он, вероятно, все еще хочет эту функцию.
DNS

1
Правильно, но ему нужно знать, что никого не существует, так как это его главный вопрос.
Джереми Л

2
Вы также должны указать значение по умолчанию, равное 1, иначе оно не будет выполнено в нулевом случае. Произведение пустой последовательности определено как 1.
Аарон Робсон

3
@CraigMcQueen Numeric является (одним из) предшественников numpy.
Tacaswell

22

Использовать это

def prod(iterable):
    p = 1
    for n in iterable:
        p *= n
    return p

Так как нет встроенной prodфункции.


6
Вы должны думать, что сокращение действительно антипаттерн :)
zweiterlinde

1
Он хотел знать, существует ли существующая функция, которую он может использовать.
Джереми Л

И этот ответ объясняет, что его нет.
EBGreen

5
@zweiterlinde: для новичков, сокращение приводит к проблемам. В этом случае, используя lambda a,b: a*b, это не проблема. Но сокращение не обобщает хорошо, и подвергается насилию. Я предпочитаю, чтобы новички не изучали это.
S.Lott

@ S.Lott Я никогда не видел, чтобы кто-то из новичков использовал Reduce, а тем более любые другие функционально-подобные конструкции. Черт, даже «промежуточные» программисты обычно не знают ничего, кроме понимания списка.
Матин Улхак,


2

Возможно, не «встроенный», но я считаю его встроенным. в любом случае просто использовать NumPy

import numpy 
prod_sum = numpy.prod(some_list)

Это опасно близко к утверждению «работает на моей машине»! Numpy, хотя он и симпатичен, однозначно не является встроенным.
RCross
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.