用Python计算两个列表的乘积总和?

2 投票
2 回答
1605 浏览
提问于 2025-04-17 22:23

我在用 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 个回答

1

使用一个简单的生成器表达式:

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 的工作方式稍有不同,当你传入多个序列且它们的长度不同时。

3

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

注意,termscoefficients 的顺序是有影响的,但除此之外,这几种写法的时间差别不大。对于更大的输入,它们的表现也差不多:

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 中, zipmap 返回的是迭代器,所以

sum(t*c for t, c in zip(terms, coefficients))    
sum(map(op.mul, coefficients, terms))

也会很节省内存。

撰写回答