Wie kann ich alle Elemente in einer Liste zusammen mit Python multiplizieren?


204

Ich muss eine Funktion schreiben, die eine Liste von Zahlen nimmt und sie miteinander multipliziert . Beispiel: [1,2,3,4,5,6]wird mir geben 1*2*3*4*5*6. Ich könnte deine Hilfe wirklich gebrauchen.

Antworten:


208

Python 3: benutze functools.reduce:

>>> from functools import reduce
>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720

Python 2: benutze reduce:

>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720

Für die Kompatibilität mit 2 und 3 pip install sixgilt dann:

>>> from six.moves import reduce
>>> reduce(lambda x, y: x*y, [1,2,3,4,5,6])
720

Sie importieren keinen Operator, daher ist diese Lösung etwas kompakter. Ich frage mich, was schneller ist.
Jheld

30
@jheld: Ich habe die Produktion der Zahlen von 1 bis 100 zeitlich festgelegt. Sowohl in Python2 als auch in Python 3 wurden lambdadurchschnittlich 0,02 Sekunden / 1000 Wiederholungen benötigt, während operator.mulim Durchschnitt 0,009 Sekunden / 1000 Wiederholungen durchgeführt wurden, wodurch operator.muleine Größenordnung schneller wurde.
Whereswalden

4
@Wordsforthewise ist es wahrscheinlich, dass das Durchlaufen einer zusätzlichen Funktion (Lambda) Overhead hinzufügt, während operator.muldirekt zu C.
Whereswalden

4
Ich würde .009 wirklich nicht eine Größenordnung niedriger als .02 nennen. Es ist nur etwa die Hälfte.
11.

1
Ab Python 3.8 ist dies einfach möglich math.prod([1,2,3,4,5,6]). (erfordert natürlich den Import)
Tomerikoo

168

Sie können verwenden:

import operator
import functools
functools.reduce(operator.mul, [1,2,3,4,5,6], 1)

Siehe reduceund operator.mulDokumentationen für eine Erklärung.

Sie benötigen die import functoolsZeile in Python 3+.


32
Beachten Sie, dass in Python3 die reduce()Funktion aus dem globalen Namespace entfernt und im functoolsModul platziert wurde. In Python3 müssen Sie also sagen from functools import reduce.
Eugene Yarmash

2
Die '1' als drittes Argument ist hier nicht erforderlich. Was wäre ein Fall, in dem sie benötigt würde?
Worte für den

5
@wordsforthewise ohne das dritte Argument, es löst eine TypeError-Ausnahme aus, wenn Sie eine leere Sequenz übergeben
Francisco Couzo

1
lambda x,y: x*yfunktioniert auch anstelle vonoperator.mul

78

Ich würde das verwenden numpy.prod, um die Aufgabe auszuführen. Siehe unten.

import numpy as np
mylist = [1, 2, 3, 4, 5, 6] 
result = np.prod(np.array(mylist))  

13
Praktisch, wenn Sie Numpy bereits verwenden. Sie müssen es wahrscheinlich nicht einmal zuerst als Liste besetzen, dies sollte in den meisten Fällen funktionierenresult = np.prod(mylist)
Nick

4
Zwei Dinge, auf die Sie achten sollten : 1) Es kann überlaufen, insbesondere wenn die Standardeinstellung numpy.int32wie oben verwendet wird. 2) Bei kleinen Listen ist dies erheblich langsamer, da NumPy ein Array zuweisen muss (relevant, wenn es häufig wiederholt wird)
Disenchanted

1
Überlauf für Werte über 21 hiernp.prod(np.array(range(1,21)))
PatrickT

Es ist keine gute Wahl. Es kann überlaufen und ist langsamer. versuche es reduce.
Peyman

57

Wenn Sie das Importieren von Objekten und komplexere Bereiche von Python vermeiden möchten, können Sie eine einfache for-Schleife verwenden

product = 1  # Don't use 0 here, otherwise, you'll get zero 
             # because anything times zero will be zero.
list = [1, 2, 3]
for x in list:
    product *= x

7
Kleinere Anmerkung: Slices in Python sind sehr einfach, und da es sich hier nur um Grundelemente handelt, können Sie den kleinen Klumpen vermeiden, mit 1 zu beginnen, indem Sie mit Liste [0] beginnen und über Liste [1:] iterieren. Obwohl es auf lange Sicht wertvoll ist, sich mit den funktionaleren "Reduzieren" -Antworten hier vertraut zu machen, ist es auch unter anderen Umständen nützlich.
Kungphu

@kungphu Das leere Produkt wird normalerweise als 1 definiert. Ihre Lösung würde stattdessen eine IndexError-Ausnahme auslösen, wenn Sie eine leere Sequenz übergeben
Francisco Couzo

@Francisco Zugegeben, aber diese Funktion sollte in diesem Fall wahrscheinlich eine Ausnahme machen, da eine leere Sequenz eine ungültige Eingabe für diese Funktion wäre. Tatsächlich ist diese Funktion für keine Sequenz mit weniger als zwei Werten von Bedeutung. Wenn Sie eine Sequenz mit einem Wert übergeben und mit 1 multiplizieren, haben Sie im Wesentlichen einen Wert hinzugefügt, der nicht vorhanden war, was ein unerwartetes Verhalten darstellt.
Kungphu

1
@kungphu, das Verhalten für diese Antwort ist korrekt, dh das Übergeben einer Liste mit der Länge 1 gibt den Wert zurück, und das Übergeben einer Liste mit der Länge 0 gibt 1 zurück. Es ist dieselbe Denkrichtung, die sum ([]) als 0 oder sum ergibt ([3]) als 3. Siehe: en.wikipedia.org/wiki/Empty_product
emorris

Ich verstehe Ihren Standpunkt in Bezug auf mathematische Funktionen. In einer praktischen Entwicklungssituation würde ich es jedoch als eine sehr seltene Situation bezeichnen, in der eine Funktion, die explizit für die Eingabe vorgesehen ist , einen Wert zurückgeben sollte , der keine Eingabe oder ungültige Eingabe darstellt. Ich nehme an, es hängt vom Ziel der Übung ab: Wenn es nur darum geht, die Standardbibliothek zu replizieren, OK, lehrt es die Leute vielleicht etwas darüber, wie die (oder eine) Sprache implementiert ist oder implementiert werden kann. Ansonsten würde ich sagen, dass es eine gute Gelegenheit verpasst, eine Lektion über gültige und ungültige Argumente zu erteilen.
Kungphu

14

Ab dem Start Python 3.8wurde eine .prodFunktion in das mathModul in der Standardbibliothek aufgenommen:

math.prod(iterable, *, start=1)

Die Methode gibt das Produkt eines startWerts (Standard: 1) mal einer iterierbaren Zahl zurück:

import math
math.prod([1, 2, 3, 4, 5, 6])

>>> 720

Wenn die Iterable leer ist, wird dies erzeugt 1(oder der startWert, falls angegeben).


10

Hier sind einige Leistungsmessungen von meinem Computer. Relevant für den Fall, dass dies für kleine Eingaben in einer langen Schleife durchgeführt wird:

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}')

Ergebnisse:

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

Sie können sehen, dass Numpy bei kleineren Eingaben etwas langsamer ist, da es ein Array zuweist, bevor die Multiplikation durchgeführt wird. Achten Sie auch auf den Überlauf in Numpy.


Sie könnten den Auswertungsweg nur aus Neugier
hinzufügen

Ich vermute , dass multiply_functoolsund zeichnen multiply_numpy sich durch zu sehen , die gewogen np, functoolsund operatorGlobals, gefolgt von Attribut - Lookups. Würde es Ihnen etwas ausmachen, zu Einheimischen zu wechseln? _reduce=functools.reduce, _mul = operator.mul` in der Funktionssignatur, dann return _reduce(_mul, iterable)im Körper usw.
Martijn Pieters

1
Außerdem muss die Numpy-Version zuerst die Zahlen in ein Numpy-Array konvertieren. Normalerweise hätten Sie diese Konvertierung bereits vorgenommen, um dies in das Timing einzubeziehen, ist nicht wirklich fair. Wenn die Liste einmal in ein Numpy-Array konvertiert wird, wird die np.prod()Option mit 100 oder mehr Elementen am schnellsten gestartet .
Martijn Pieters

8

Ich persönlich mag dies für eine Funktion, die alle Elemente einer generischen Liste miteinander multipliziert:

def multiply(n):
    total = 1
    for i in range(0, len(n)):
        total *= n[i]
    print total

Es ist kompakt, verwendet einfache Dinge (eine Variable und eine for-Schleife) und fühlt sich für mich intuitiv an (es sieht so aus, als würde ich das Problem betrachten, nehmen Sie einfach eines, multiplizieren Sie es, multiplizieren Sie es mit dem nächsten und so weiter! )


3
großartig, es ist das einfachste und einfachste.
Ghostkraviz

4
Warum nicht for i in n:, dann total *= i? wäre es nicht viel einfacher?
Munim Munna

@ MunimMunnaEs hat bei mir nicht so funktioniert wie oben.
Athul

5

Der einfache Weg ist:

import numpy as np
np.exp(np.log(your_array).sum())

10
Was ist mit nurnp.prod(your_Array)
schneidigen

3

Numpyhat die prod()Funktion, die das Produkt einer Liste zurückgibt, oder in diesem Fall, da es numpy ist, ist es das Produkt eines Arrays über einer bestimmten Achse:

import numpy
a = [1,2,3,4,5,6]
b = numpy.prod(a)

... oder Sie können einfach importieren numpy.prod():

from numpy import prod
a = [1,2,3,4,5,6]
b = prod(a)

2

Ich habe diese Frage heute gefunden, aber ich habe festgestellt, dass es nicht den Fall gibt None, in dem es in der Liste gibt. Die vollständige Lösung wäre also:

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

Im Falle der Hinzufügung haben wir:

print(reduce(lambda x, y: (x if x else 0) + (y if y else 0), a))

2
nums = str(tuple([1,2,3]))
mul_nums = nums.replace(',','*')
print(eval(mul_nums))

5
Bitte fügen Sie Ihrer Antwort eine Erklärung hinzu. Wie zu
antworten

3
Ich stimme zu und versuche, den Code zu erklären: Ich persönlich mag diesen Code nicht sehr, da er eval verwendet, das die Zeichenfolge als Argument oder Funktion interpretiert (und daher allgemein als unsicher angesehen wird, insbesondere beim Umgang mit Eingabedaten ). Die Zeile davor ersetzt jedes begrenzende Komma durch ein Multiplikativ *, sodass eval dies als Multiplikativ erkennt. Ich frage mich, wie die Leistung diesbezüglich ist, insbesondere im Vergleich zu anderen Lösungen
Dennlinger

Wow, so eine schlechte Idee!
Kowalski

1

Ich möchte dies folgendermaßen:

    def product_list(p):
          total =1 #critical step works for all list
          for i in p:
             total=total*i # this will ensure that each elements are multiplied by itself
          return total
   print product_list([2,3,4,2]) #should print 48

1

Das ist mein Code:

def product_list(list_of_numbers):
    xxx = 1
    for x in list_of_numbers:
        xxx = xxx*x
    return xxx

print(product_list([1,2,3,4]))

Ergebnis: ('1 * 1 * 2 * 3 * 4', 24)


0

Wie wäre es mit Rekursion?

def multiply(lst):
    if len(lst) > 1:
        return multiply(lst[:-1])* lst[-1]
    else:
        return lst[0]

-1

Meine Lösung:

def multiply(numbers):
    a = 1
    for num in numbers:
        a *= num
        return a

  pass

-1

'' 'die einzige einfache Methode, um die Logik für die Schleife zu verstehen' ''

Runde = [2,5,7,7,9] x = 1 für i in Runde: x = i * x print (x)


Ihre Antwort fügt der Diskussion dieser Frage nichts Neues hinzu.
Sid

-3

Es ist sehr einfach, nichts zu importieren. Das ist mein Code. Dadurch wird eine Funktion definiert, die alle Elemente in einer Liste multipliziert und ihr Produkt zurückgibt.

def myfunc(lst):
    multi=1
    for product in lst:
        multi*=product
    return product

2
Duplizieren Sie die Antwort von DeadChex, die Antwort von piSHOCK, die Antwort von Shakti Nandan. Veröffentlichen Sie keine bereits vorgeschlagene Antwort.
Munim Munna

es sollte auch multi | - | zurückgeben
Lars
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.