Jaka jest funkcja sum (), ale do mnożenia? produkt()?

206

sum()Funkcja Pythona zwraca sumę liczb w iterowalnym.

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

Szukam funkcji, która zwraca produkt zamiast tego.

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

Jestem pewien, że taka funkcja istnieje, ale nie mogę jej znaleźć.

Patrick McElhaney
źródło

Odpowiedzi:

71

Aktualizacja:

W Pythonie 3.8 funkcja prod została dodana do modułu matematycznego . Zobacz: math.prod () .

Starsze informacje: Python 3.7 i wcześniejsze

Funkcja, której szukasz, nazywa się prod () lub product (), ale Python nie ma tej funkcji. Musisz więc napisać własny (co jest łatwe).

Wymowa on prod ()

Tak to prawda. Guido odrzucił pomysł wbudowanej funkcji prod (), ponieważ uważał, że rzadko jest ona potrzebna.

Alternatywnie z redukcją ()

Jak zasugerowałeś, nie jest trudno stworzyć własne za pomocą funkcji replace () i operator.mul () :

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

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

Uwaga: w Pythonie 3 funkcja zmniejszania () została przeniesiona do modułu funkools .

Przypadek szczególny: czynniki

Na marginesie, głównym motywującym zastosowaniem dla prod () jest obliczenie silni. Mamy już na to wsparcie w module matematycznym :

>>> import math

>>> math.factorial(10)
3628800

Alternatywa z logarytmami

Jeśli twoje dane składają się z liczb zmiennoprzecinkowych, możesz obliczyć produkt za pomocą sum () z wykładnikami i logarytmami:

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

Uwaga: użycie log () wymaga, aby wszystkie dane wejściowe były dodatnie.

Raymond Hettinger
źródło
Możesz dodać, że zmiennoprzecinkowe w ostatnim przykładzie muszą być dodatnie . W przeciwnym razie może być konieczne użycie cmath, ale nawet wtedy tak naprawdę nie zadziała we wszystkich przypadkach.
Veky
212

Właściwie Guido zawetował pomysł: http://bugs.python.org/issue1093

Ale, jak zauważono w tym numerze, możesz łatwo go utworzyć:

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

reduce(operator.mul, (3, 4, 5), 1)
ojrac
źródło
4
Oto świetny przykład tego, gdzie jest „potrzeba”, aby zacytować Guido: produkt (filtr (Brak, [1,2,3, Brak])). Mam nadzieję, że zostanie to kiedyś włączone.
the911s
13
Czy Guido nie jest też facetem, który nie lubi reduce?
Chris Martin
3
Tak - i redukcja nie jest już nawet wbudowana w Pythona 3. IMO, nie potrzebujemy wszystkich możliwych operatorów list dodawanych do globalnych wbudowań, gdy robiłaby to standardowa biblioteka (lub innej firmy). Im więcej wbudowanych funkcji, tym częstsze słowa stają się niedostępne jako lokalne nazwy zmiennych.
ojrac
7
Właśnie znalazłem ten samorodek w poście Guido na blogu o zmniejszeniu () . „Mamy już sumę (); chętnie zamienię redukcję () na produkt () ...” . Jeśli ktoś chce złożyć wniosek o włączenie product()do standardowej biblioteki, liczba poglądów na to pytanie może pomóc w uzasadnieniu sprawy.
Patrick McElhaney,
1
@PatrickMcElhaney Wygląda na to, że python3 już pozbył się wbudowanej funkcji redukcji. Myślę, że produkt stracił swoją szansę. ;)
ojrac
41

Nie ma żadnego wbudowanego, ale łatwo go wyrzucić, jak pokazano tutaj :

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

Zobacz odpowiedzi na to pytanie:

Który moduł Python nadaje się do manipulacji danymi na liście?

zweiterlinde
źródło
8
Jeśli używasz Python 3 użyj functools.reducezamiast reduce.
Steven Rumbalski
1
Jeszcze więcej funools fun:prod = functools.partial(functools.reduce, operator.mul)
bukzor
39

Jest prod()numpy, która robi to, o co prosisz.

Benzoes
źródło
3
Uwaga: nie obsługuje długich Python (liczb całkowitych o dowolnej precyzji), więc np.prod(range(1,13))daje poprawną odpowiedź równą 12! ale np.prod(range(1,14))nie ma.
Jason S
2
@JasonS np.prod(arange(1,14, dtype='object'))?
endolith
1
math.prod()Funkcja będzie to odpowiedź nieaktualne.
Benoît P
Nadal żmudne jest importowanie matematyki, gdy chcesz to zrobić w prostej linijce. Tęsknię za redukcją () i produktem odrzuconym przez Guido ().
RCross
25
Numeric.product 

(lub

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

)

Steve B.
źródło
Chce funkcji, którą może załadować z modułu lub biblioteki, a nie sam pisać funkcji.
Jeremy L
2
Ale jeśli go nie ma, prawdopodobnie nadal chce tej funkcji.
DNS
1
Zgadza się, ale musi wiedzieć, że nie istnieje, ponieważ to jest jego główne pytanie.
Jeremy L
2
Musisz również podać wartość domyślną zmniejszoną o 1, w przeciwnym razie nie powiedzie się w przypadku wartości zerowej. Iloczyn pustej sekwencji jest zdefiniowany jako 1.
Aaron Robson
3
@CraigMcQueen Numeric jest (jednym z) poprzedników numpy.
tacaswell
22

Użyj tego

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

Ponieważ nie ma wbudowanej prodfunkcji.

S.Lott
źródło
6
musisz myśleć, że redukcja naprawdę jest antypatternem
zweiterlinde
1
Chciał wiedzieć, czy istnieje istniejąca funkcja, której można użyć.
Jeremy L
Ta odpowiedź wyjaśnia, że ​​nie ma takiej.
EBGreen
5
@zweiterlinde: dla początkujących zmniejsz liczbę potencjalnych problemów. W takim przypadku korzystanie z lambda a,b: a*bniego nie stanowi problemu. Ale redukcja nie uogólnia się i jest wykorzystywana. Wolę, żeby początkujący go nie uczyli.
S.Lott
@ S.Lott Nigdy nie widziałem, aby użytkownicy początkujący używali redukcji, a tym bardziej innych funkcjonalnych konstrukcji. Do diabła, nawet programiści „pośredni” zwykle nie wiedzą wiele poza zrozumieniem listy.
Mateen Ulhaq
2

Być może nie jest to „wbudowane”, ale uważam, że jest wbudowane. w każdym razie po prostu użyj numpy

import numpy 
prod_sum = numpy.prod(some_list)
katiex7
źródło
To niebezpiecznie zbliżone do stwierdzenia „działa na mojej maszynie”! Numpy, choć piękne, jest jednoznaczne, a nie wbudowane.
RCross