用Python计算两个列表的乘积总和?
我在用 sympy
的时候,有两个列表:
terms = [1, x, x*(x-1)]
coefficients = [-1,8.1,7]
我想要得到这样的输出:
-1+8.1*x+7*x(x-1)
我试过:
print (sum(a,x__i) for a, x__i in izip(terminos,coeficientes))
但是我实际上得到了一个 generator
,我是根据一段能用的代码尝试的:
def lag_l(xx, j):
x = Symbol("x")
parts = ((x - x_i) / (xx[j] - x_i) for i, x_i in enumerate(xx) if i != j)
return prod(parts)
def lag_L(xx, yy):
return sum(y*lag_l(xx, j) for j, y in enumerate(yy))
我该怎么做才能完成这个呢?
2 个回答
使用一个简单的生成器表达式:
sum(coef * term for coef, term in zip(coefficients, terms))
另外,如果你不想用 zip
,可以考虑用类似 zip_with
的东西:
def zip_with(operation, *iterables):
for elements in zip(*iterables):
yield operation(*elements)
然后可以这样使用:
import operator as op
sum(zip_with(op.mul, coefficients, terms))
正如 unutbu 提到的,Python 其实已经提供了这样的功能,在 itertools.imap
中(适用于 Python 2),以及内置的 map
(适用于 Python 3),所以你可以避免重新编写这个功能,直接使用:
sum(itertools.imap(op.mul, coefficients, terms))
或者
sum(map(op.mul, coefficients, terms) #python3
在 Python 2 中,map
的工作方式稍有不同,当你传入多个序列且它们的长度不同时。
In [159]: import sympy as sy
In [160]: from sympy.abc import x
In [161]: terms = [1, x, x*(x-1)]
In [162]: coefficients = [-1,8.1,7]
In [163]: sum(t*c for t, c in zip(terms, coefficients))
Out[163]: 7*x*(x - 1) + 8.1*x - 1
有趣的是,sum(term*coef for term, coef in zip(terms, coefficients))
这个写法比 sum(coef * term for coef, term in zip(coefficients, terms))
要快一点:
In [182]: %timeit sum(term * coef for term, coef in zip(terms, coefficients))
10000 loops, best of 3: 34.1 µs per loop
In [183]: %timeit sum(coef * term for coef, term in zip(coefficients, terms))
10000 loops, best of 3: 38.7 µs per loop
原因在于,coef * term
这个操作会调用 coef.__mul__(term)
,然后又得调用 term.__rmul__(coef)
,因为整数(ints)不知道怎么和 sympy
的符号(Symbols)相乘。这个额外的函数调用让 coef * term
比 term * coef
慢。(term * coef
直接调用 term.__mul__(coef)
。)
这里还有一些更详细的性能测试:
In [178]: %timeit sum(IT.imap(op.mul, coefficients, terms))
10000 loops, best of 3: 38 µs per loop
In [186]: %timeit sum(IT.imap(op.mul, terms, coefficients))
10000 loops, best of 3: 32.8 µs per loop
In [179]: %timeit sum(map(op.mul, coefficients, terms))
10000 loops, best of 3: 38.5 µs per loop
In [188]: %timeit sum(map(op.mul, terms, coefficients))
10000 loops, best of 3: 33.3 µs per loop
注意,terms
和 coefficients
的顺序是有影响的,但除此之外,这几种写法的时间差别不大。对于更大的输入,它们的表现也差不多:
In [203]: terms = [1, x, x*(x-1)] * 100000
In [204]: coefficients = [-1,8.1,7] * 100000
In [205]: %timeit sum(IT.imap(op.mul, terms, coefficients))
1 loops, best of 3: 3.63 s per loop
In [206]: %timeit sum(term * coef for term, coef in zip(terms, coefficients))
1 loops, best of 3: 3.63 s per loop
In [207]: %timeit sum(map(op.mul, terms, coefficients))
1 loops, best of 3: 3.48 s per loop
另外要知道,如果你没有通过性能分析(profiling)发现这个操作是你代码中的瓶颈,那么担心这些微小的差别其实是浪费时间,因为为了提前优化这些东西所花的时间远远超过了你在代码运行时节省的时间。正如人们所说,过早优化是万恶之源。我可能已经犯了这个错误。
在 Python2 中,
sum(IT.imap(op.mul, coefficients, terms))
使用的内存最少。
在 Python3 中, zip
和 map
返回的是迭代器,所以
sum(t*c for t, c in zip(terms, coefficients))
sum(map(op.mul, coefficients, terms))
也会很节省内存。