Python中计算点积的惯用方法是什么?

38

我有两个列表,一个叫做A,另一个叫做B。 A中的每个元素都是三元组,而B中的每个元素都只是一个数字。我想计算定义为:

result = A[0][0] * B[0] + A[1][0] * B[1] + ... + A[n-1][0] * B[n-1]

我知道逻辑很简单,但如何用Pythonic的方式编写呢?

谢谢!


A 的结构是一个二维列表/矩阵。 - igauravsehrawat
12个回答

77

Python 3.5 版本引入了显式的运算符@来执行点积运算,因此您可以这样编写代码

a = A @ B

取代

a = numpy.dot(A,B)

2
请参阅 https://dev59.com/OFcO5IYBdhLWcg3wrDVq 了解一个警告。 - mic
7
实际上,“@”运算符是NumPy的运算符,而不是Python的。 - Walter Tross
5
@WalterTross 中的 @ 是 Python 的符号,尽管它目前并未使用。Numpy 在其数组中实现了该符号。 - GeeTransit
3
@ 运算符是专门用于矩阵乘法的,因此 numpy 并没有胡乱发明:https://www.python.org/dev/peps/pep-0465/ (只是基本的 Python 没有矩阵而已) - remram
3
这篇文章让人觉得[1,2,3] @ [2,1,1]应该可以工作,但实际上并不行。 - run_the_race
显示剩余3条评论

40

32

我最喜欢的Pythonic点积是:

sum([i*j for (i, j) in zip(list1, list2)])


对于您的情况,我们可以这样做:

sum([i*j for (i, j) in zip([K[0] for K in A], B)])

3
在求和之前先构建整个列表 - Walter Tross

24
from operator import mul

sum(map(mul, A, B))

4

使用operator和itertools模块:

from operator import mul
from itertools import imap

sum(imap(mul, A, B))

1
在 Python 3.0 及以上版本中,map 函数的行为类似于 imap 函数:https://docs.python.org/3.0/whatsnew/3.0.html#views-and-iterators-instead-of-lists - xuiqzy

3

使用第三方库more_itertools,它实现了dotproduct itertools recipe

import more_itertools as mit


a = [1, 2, 3]
b = [7, 8, 9]

mit.dotproduct(a, b)
# 50

3

人们正在重新分配@运算符作为点积运算符。这是使用纯Python的zip函数返回元组的代码。然后使用列表推导式代替map函数。

def dot_product(a_vector,b_vector):
    #a1 x b1 + a2 * b2..an*bn return scalar
    return sum([an*bn for an,bn in zip(a_vector,b_vector)])

X = [2,3,5,7,11]
Y = [13,17,19,23,29]
print(dot_product(X,Y)) #652

a=[1,2,3]
b=[4,5,6]
print(dot_product(a,b)) #prints 32= 1*4 + 2*5 + 3*6 = 
a = [1, 2, 3]
b = [7, 8, 9]
print(dot_product(a,b)) #prints 50 

2
>>> X = [2,3,5,7,11]
>>> Y = [13,17,19,23,29]
>>> dot = lambda X, Y: sum(map(lambda x, y: x * y, X, Y))
>>> dot(X, Y)
652

就是这样。


1

对于这种情况,可能最Pythonic的方法是使用numpy。;-)


1
在Python 3.12+中,你可以使用math.sumprod
考虑到你的情况。
A = [
    (1, 11, 111),
    (2, 22, 222),
]
B = [10, 100]

first_column = (row[0] for row in A)

你可以用 A[0][0] * B[0] + A[1][0] * B[1] 进行计算。
>>> import math
>>> math.sumprod(first_column, B)
210

在旧版本中,可能最符合Python风格的方式是使用生成器(即,不构建中间列表)与sum函数一起使用。
>>>  sum(row[0] * b for row, b in zip(A, B, strict=True))
210

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接