如何将列表中的所有项目与Python相乘?


204

我需要编写一个函数,该函数接受一个数字列表并将它们相乘。例子: [1,2,3,4,5,6]会给我的1*2*3*4*5*6。我真的可以用你的帮助。

Answers:


208

Python 3:使用functools.reduce

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

Python 2:使用reduce

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

为了与2和3兼容,请使用pip install six

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

您无需导入运算符,因此此解决方案更加紧凑。我想知道哪个更快。
jheld 2014年

30
@jheld:我定时将乘积乘以1到100。在python2和3中,lambda平均重复数为.02s / 1000,而operator.mul平均重复数为.009s / 1000,operator.mul加快了一个数量级。
whereswalden 2014年

4
@wordsforthewise可能它是要通过一个额外的功能(拉姆达)增加了开销,而operator.mul直接转到C.
whereswalden

4
我真的不会称呼.009比.02低一个数量级。大约一半。
jlh

1
从Python 3.8开始,可以使用完成math.prod([1,2,3,4,5,6])。(需要导入课程)
Tomerikoo

168

您可以使用:

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

有关说明,请参见reduceoperator.mul文档。

您需要import functoolsPython 3+中的代码行。


32
请注意,在python3中,该reduce()函数已从全局名称空间中删除,并放置在functools模块中。因此,在python3中,您需要说from functools import reduce
Eugene Yarmash 2013年

2
这里不需要使用“ 1”作为第三个参数,在什么情况下需要使用“ 1”呢?
wordforthewise

5
@wordsforthewise,不带第三个参数,如果将空序列传递给它,则会引发TypeError异常
Francisco Couzo 2016年

1
lambda x,y: x*y也可以代替operator.mul

78

我会使用numpy.prod来执行任务。见下文。

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

13
如果您已经在使用Numpy,则非常方便。您可能甚至不需要首先将其转换为列表,这在大多数情况下都应适用result = np.prod(mylist)
Nick

4
需要注意两件事: 1)它可能会溢出,尤其是如果使用numpy.int32上面 的默认值时2)对于小列表,这会明显变慢,因为NumPy需要分配一个数组(如果经常重复,则是相关的)
2017年

1
此处的值大于21将溢出np.prod(np.array(range(1,21)))
PatrickT

这不是一个好选择。它可能溢出,并且速度较慢。尝试一下reduce
Peyman

57

如果要避免导入任何内容并避免使用更复杂的Python区域,则可以使用简单的for循环

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
小注释:Python中的切片非常简单,并且由于我们这里仅处理基元,因此可以通过从list [0]开始并遍历list [1:]来避免从1开始的小麻烦。从长远来看,尽管对功能更强大的“减少”答案感到满意是很有价值的,因为它在其他情况下也很有用。
kungphu 2013年

@kungphu空产品通常定义为1,如果将空序列传递给它,则解决方案将引发IndexError异常
Francisco Couzo

@Francisco授予,但是在这种情况下此函数可能应该抛出某种异常,因为空序列对该函数而言将是无效的输入。实际上,此函数对于任何少于两个值的序列都没有意义;如果传递一个带有一个值的序列并将其乘以1,则实际上已经添加了一个不存在的值,我想说这等于意外的行为。
kungphu

1
@kungphu,此答案的行为是正确的,即,传递长度为1的列表将返回值,传递长度为0的列表将返回1。这与将sum([])设为0或sum相同([3])为3。请参见:en.wikipedia.org/wiki/Empty_product
emorris

我明白您关于数学函数的观点。但是,在实际的开发情况下,我将其称为一种非常罕见的情况,其中明确打算对输入进行操作的函数应该在没有输入或无效输入的情况下返回一个值。我想这取决于练习的目的:如果只是为了复制标准库,可以,也许它可以教给人们一些有关(或一种)语言的实现方式。否则,我会说它错过了提供有关有效和无效参数的课程的好机会。
kungphu

14

从开始Python 3.8.prod函数已经包含math在标准库的模块中:

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

该方法返回一个start值(默认值:1)乘以数字可迭代的乘积:

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

>>> 720

如果iterable为空,则将产生1(或start提供值,如果提供)。


10

这是我机器上的一些性能指标。与在长时间运行的循环中对较小的输入执行此操作有关:

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

结果:

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

您会看到Numpy在较小的输入上要慢得多,因为它在执行乘法之前会分配一个数组。另外,请注意Numpy中的溢出。


您可以出于好奇而添加评估方式
Mr_and_Mrs_D

我怀疑multiply_functools,并multiply_numpy 具有以查找被拖累npfunctools以及operator全局,其次属性查找。您介意切换到当地人吗?_reduce=functools.reduce, _mul = operator.mul`在函数签名然后return _reduce(_mul, iterable)在体内,等等
马亭皮特斯

1
同样,numpy版本必须首先将数字转换为numpy数组;您通常已经进行了转换,将其包括在时间范围内并不是很公平。将列表一次转换为numpy数组后,np.prod()选项启动速度最快达到100个元素或更多。
马丁·彼得

8

我个人对将通用列表的所有元素相乘的函数喜欢这样:

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

它紧凑,使用简单的东西(变量和for循环),并且对我来说很直观(看起来就像我对问题的看法,只用一个,乘以它,然后乘以下一个,依此类推! )


3
太好了,它是最简单,最简单的。
ghostkraviz

4
为什么不能for i in n:,那么total *= i?会不会简单得多?
Munim Munna '18

@MunimMunnaIt以上方法对我没有用。
–'Athul

5

简单的方法是:

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

10
怎么样np.prod(your_Array)
破旧的

3

Numpy具有prod()返回列表乘积的函数,或者在这种情况下,因为它是numpy,所以它是给定轴上数组的乘积:

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

...否则您可以只导入numpy.prod()

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

2

今天发现了这个问题,但我注意到列表中没有的情况None。因此,完整的解决方案将是:

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

对于加法,我们有:

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
请在回答中添加一些解释。如何回答
xenteros

3
我插话并尝试解释代码:我个人不太喜欢此代码,因为它使用eval,它将字符串解释为参数或函数(因此通常被认为是不安全的事情,尤其是在处理输入数据时) )。之前的行用乘数替换每个定界逗号*,这样eval会将其识别为乘数。我想知道这样做的性能如何,尤其是与其他解决方案相比
dennlinger

哇,好主意!
科瓦尔斯基

1

我想通过以下方式:

    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

这是我的代码:

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

结果:('1 * 1 * 2 * 3 * 4',24)


0

如何使用递归?

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



-3

很简单,不导入任何内容。这是我的代码。这将定义一个将列表中所有项目相乘并返回其乘积的函数。

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

2
与DeadChex的答案,piSHOCK的答案,Shakti Nandan的答案重复。不要发布已经建议的答案。
Munim Munna

它也应该返回多个|-|
拉斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.