¿Cómo puedo multiplicar todos los elementos de una lista junto con Python?


204

Necesito escribir una función que tome una lista de números y los multiplique . Ejemplo: [1,2,3,4,5,6]me dará 1*2*3*4*5*6. Realmente podría usar tu ayuda.

Respuestas:


208

Python 3: uso functools.reduce:

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

Python 2: uso reduce:

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

Para uso compatible con 2 y 3 pip install six, entonces:

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

No importa operador, por lo que esta solución es un poco más compacta. Me pregunto cuál es más rápido.
jheld

30
@jheld: cronometré produciendo los números del 1 al 100. En python2 y 3, lambdatomé un promedio de .02s / 1000 repeticiones, mientras que operator.multomé un promedio de .009s / 1000 repeticiones, haciendo operator.mulun orden de magnitud más rápido.
Whereswalden

44
@wordsforthewise probable es que va a través de una función adicional (lambda) implica una sobrecarga, mientras que operator.mulva directamente a C
whereswalden

44
Realmente no llamaría .009 un orden de magnitud inferior a .02. Es casi la mitad.
jlh

1
A partir de Python 3.8, se puede hacer simplemente con math.prod([1,2,3,4,5,6]). (requiere importación, por supuesto)
Tomerikoo

168

Puedes usar:

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

Ver reduceyoperator.mul documentaciones para una explicación.

Necesitas la import functoolslínea en Python 3+.


32
Tenga en cuenta que en python3, la reduce()función se ha eliminado del espacio de nombres global y se ha colocado en el functoolsmódulo. Entonces, en python3 necesitas decir from functools import reduce.
Eugene Yarmash

2
El '1' como tercer argumento es innecesario aquí, ¿cuál es el caso donde sería necesario?
wordsforthewise

55
@wordsforthewise sin el tercer argumento, arroja una excepción TypeError si le pasa una secuencia vacía
Francisco Couzo

1
lambda x,y: x*ytambién funciona en lugar deoperator.mul

79

Usaría el numpy.prodpara realizar la tarea. Vea abajo.

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

13
Conveniente si ya estás usando Numpy. Probablemente ni siquiera necesite lanzarlo primero como una lista, esto debería funcionar para la mayoría de los casosresult = np.prod(mylist)
Nick

44
Hay dos cosas a tener en cuenta: 1) Puede desbordarse, especialmente si se usa el valor predeterminado numpy.int32como el anterior 2) Para listas pequeñas esto será significativamente más lento, ya que NumPy necesita asignar una matriz (relevante si se repite con frecuencia)
Desencantado el

1
desbordamiento para valores superiores a 21 aquínp.prod(np.array(range(1,21)))
PatrickT

No es una buena elección. Puede desbordarse y es más lento. tratar reduce.
Peyman

57

Si desea evitar importar algo y evitar áreas más complejas de Python, puede usar un bucle for simple

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

77
Nota menor: Los cortes en Python son muy fáciles, y dado que aquí solo tratamos con primitivas, puede evitar el pequeño error de comenzar con 1 comenzando con la lista [0] e iterando sobre la lista [1:]. Aunque sentirse cómodo con las respuestas de 'reducción' más funcionales aquí es valioso a largo plazo, ya que también es útil en otras circunstancias.
kungphu

@kungphu El producto vacío generalmente se define como 1, su solución arrojaría una excepción IndexError en su lugar si le pasa una secuencia vacía
Francisco Couzo

@Francisco Concedido, pero esta función probablemente debería arrojar algo de excepción en ese caso, ya que una secuencia vacía sería una entrada no válida para esta función. De hecho, esta función no es significativa para ninguna secuencia con menos de dos valores; Si pasa una secuencia con un valor y la multiplica por 1, esencialmente ha agregado un valor que no estaba allí, lo que diría que equivale a un comportamiento inesperado.
kungphu

1
@kungphu, el comportamiento de esta respuesta es correcto, es decir, pasar una lista de longitud 1 devuelve el valor y pasar una lista de longitud 0 devuelve 1. Está en la misma línea de pensamiento que da la suma ([]) como 0 o suma ([3]) como 3. Ver: en.wikipedia.org/wiki/Empty_product
emorris

Veo su punto con respecto a las funciones matemáticas. Sin embargo, en una situación de desarrollo práctico, lo llamaría una situación muy rara en la que una función que está explícitamente destinada a operar en una entrada debería devolver un valor dado que equivale a ninguna entrada o entrada no válida. Supongo que depende del objetivo del ejercicio: si es solo para replicar la biblioteca estándar, está bien, tal vez le enseñe a la gente algo sobre cómo se puede implementar o puede implementar el (o un) lenguaje. De lo contrario, diría que se pierde una buena oportunidad para proporcionar una lección sobre argumentos válidos e inválidos.
kungphu

14

Comenzando Python 3.8, .prodse ha incluido una función al mathmódulo en la biblioteca estándar:

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

El método devuelve el producto de un startvalor (predeterminado: 1) multiplicado por un iterable de números:

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

>>> 720

Si el iterable está vacío, esto producirá 1(o el startvalor, si se proporciona).


10

Aquí hay algunas mediciones de rendimiento de mi máquina. Relevante en caso de que esto se realice para entradas pequeñas en un ciclo de larga duración:

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

Resultados:

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

Puede ver que Numpy es bastante más lento en entradas más pequeñas, ya que asigna una matriz antes de que se realice la multiplicación. Además, ten cuidado con el desbordamiento en Numpy.


Puede agregar la forma de evaluación solo por curiosidad
Mr_and_Mrs_D

Sospecho eso multiply_functoolsy estoy multiply_numpy abrumado por tener que buscar el np, functoolsy los operatorglobales, seguido de búsquedas de atributos. ¿Te importaría cambiarte a locales? _reduce=functools.reduce, _mul = operator.mul` en la firma de la función y luego return _reduce(_mul, iterable)en el cuerpo, etc.
Martijn Pieters

1
Además, la versión numpy tiene que convertir primero los números a una matriz numpy; normalmente ya habrías hecho esa conversión, incluir eso en los tiempos no es realmente justo. Con la lista convertida a una matriz numpy una vez, la np.prod()opción comienza se vuelve más rápida con 100 elementos o más.
Martijn Pieters

8

Personalmente, me gusta esto para una función que multiplica todos los elementos de una lista genérica:

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

Es compacto, usa cosas simples (una variable y un bucle for), y me parece intuitivo (parece que pensaría en el problema, solo toma uno, multiplícalo, luego multiplícalo por el siguiente, ¡y así sucesivamente! )


3
genial, es el más simple y el más simple.
ghostkraviz

44
¿Por qué no for i in n:entonces total *= i? ¿No sería mucho más sencillo?
Munim Munna

@MunimMunnaNo funcionó para mí de la manera anterior.
athul

5

La forma simple es:

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

10
¿qué pasa connp.prod(your_Array)
guiones

3

Numpytiene la prod()función que devuelve el producto de una lista, o en este caso, ya que es numpy, es el producto de una matriz sobre un eje dado:

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

... o simplemente puedes importar numpy.prod():

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

2

Encontré esta pregunta hoy, pero me di cuenta de que no tiene el caso donde hay Noneen la lista. Entonces, la solución completa sería:

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

En el caso de la adición, tenemos:

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

55
Agregue alguna explicación a su respuesta. Cómo responder
xenteros

3
Interrumpo e intento explicar el código: personalmente me gusta mucho este código, ya que usa eval, que interpreta la cadena como un argumento o función (y, por lo tanto, generalmente se considera algo inseguro, especialmente cuando se manejan datos de entrada ) La línea anterior reemplaza cada coma delimitadora por un multiplicativo *, de modo que eval reconocerá esto como multiplicativo. Me pregunto cómo es el rendimiento de esto, especialmente en comparación con otras soluciones
Dennlinger

Wow, que mala idea!
Kowalski

1

Me gustaría esto de la siguiente manera:

    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

Este es mi código:

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

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


0

¿Qué tal el uso de la recursividad?

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

-1

Mi solución:

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

  pass

-1

'' 'el único método simple para comprender el uso lógico del bucle' ''

Vuelta = [2,5,7,7,9] x = 1 para i en Vuelta: x = i * x print (x)


Su respuesta no agrega nada nuevo a la discusión de esta pregunta.
Sid

-3

Es muy sencillo no importar nada. Este es mi codigo. Esto definirá una función que multiplica todos los elementos de una lista y devuelve su producto.

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

2
Duplicar la respuesta de DeadChex, la respuesta de piSHOCK, la respuesta de Shakti Nandan. No publique la respuesta que ya se sugirió.
Munim Munna

también debería devolver multi | - |
Lars
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.