Що таке функція, як 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 ()

Так, правильно. Гвідо відкинув ідею вбудованої функції prod (), оскільки вважав, що це рідко потрібно.

Альтернатива зі зменшенням ()

Як ви запропонували, не важко зробити свій власний за допомогою скорочення () та 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

Зауважте, що використання журналу () вимагає, щоб усі входи були позитивними.


Ви можете додати, що плавці в останньому прикладі повинні бути позитивними . В іншому випадку, можливо, вам доведеться використовувати cmath, але навіть тоді це не спрацює у всіх випадках.
Векі

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])). Сподіваємось, він буде включений колись.
the911s

13
Чи не Гвідо також той хлопець, який не любить reduce?
Кріс Мартін

3
Так - і скорочення вже не є вбудованим в Python 3. IMO, нам не потрібен кожен можливий оператор списку, який додається до глобальних вбудованих, коли стандартна (або третя сторона) бібліотека буде робити. Чим більше у вас вбудованих, тим більше поширених слів стає поза межами, як локальні назви змінних.
ojrac

7
Щойно знайшов цей самородок у публікації до блогу Guido про зменшення () . "У нас вже є сума (); я б із задоволенням торгував зменшити () для продукту () ..." . Якщо хтось хоче подати клопотання про включення product()до стандартної бібліотеки, кількість переглядів цього питання може допомогти зробити це.
Патрік МакЕлхані

1
@PatrickMcElhaney Це здається, що python3 вже позбувся скорочення вбудованого. Я думаю, що продукт упустив свій шанс. ;)
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)
bukzor

39

Є prod()в нуме, який робить те, що ви просите.


3
Примітка: не підтримує Python longs (довільні точні цілі числа), тому np.prod(range(1,13))дає правильну відповідь, рівну 12! але np.prod(range(1,14))ні.
Jason S

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

1
math.prod()Функція зробить цей відповідь застарілим.
Benoît P

Досі нудно імпортувати математику, коли ви хочете це зробити в простому однокласнику. Я сумую за зменшенням () та відхиленим від 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
ви повинні подумати, що зменшення насправді є
антипатерном

1
Він хотів знати, чи існує функція, яку він може використовувати.
Джеремі Л

І ця відповідь пояснює, що такого немає.
EBGreen

5
@zweiterlinde: Для початківців скорочення призводить до проблем. У цьому випадку використання lambda a,b: a*b, це не є проблемою. Але зменшення не узагальнює добре, і їх зловживають. Я вважаю за краще, щоб початківці не вчилися цьому.
S.Lott

@ S.Lott Я ніколи не бачив, щоб хтось із початківців використовував скорочення, тим більше будь-які інші функціональні конструкції. Хек, навіть "проміжні" програмісти зазвичай не знають багато іншого, ніж розуміння списку.
Матін Ульхак


2

Можливо, не "вбудований", але я вважаю це вбудованим. у будь-якому випадку просто використовуйте нуме

import numpy 
prod_sum = numpy.prod(some_list)

Це небезпечно близько до заяви "працює на моїй машині"! Незграбний, хоч і чудовий, але однозначно не є вбудованим.
RCross
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.