Python中的高效Vector/Point类

Jos*_*hua 9 python performance vector python-3.x

实现高效的Vector/Point类的最佳方法是什么(甚至更好:是否有一个),可以在Python 2.7+和3.x中使用?

我找到了blender-mathutils,但它们似乎只支持Python 3.x. 然后就是这个Vector类,它使用numpy,但它只是一个3D矢量.使用像kivy的矢量类(源代码)的矢量列表,它具有静态属性(x和y)似乎也很奇怪.(有所有这些列表方法.)

目前我正在使用一个扩展了namedtuple的类(如下所示),但这样做的缺点是无法更改坐标.我认为当数千个对象移动并且每次都创建一个新的(矢量)元组时,这可能会成为一个性能问题.(对?)

class Vector2D(namedtuple('Vector2D', ('x', 'y'))):
    __slots__ = ()

    def __abs__(self):
        return type(self)(abs(self.x), abs(self.y))

    def __int__(self):
        return type(self)(int(self.x), int(self.y))

    def __add__(self, other):
        return type(self)(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        return type(self)(self.x - other.x, self.y - other.y)

    def __mul__(self, other):
        return type(self)(self.x * other, self.y * other)

    def __div__(self, other):
        return type(self)(self.x / other, self.y / other)

    def dot_product(self, other):
        return self.x * other.x + self.y * other.y

    def distance_to(self, other):
        """ uses the Euclidean norm to calculate the distance """
        return hypot((self.x - other.x), (self.y - other.y))
Run Code Online (Sandbox Code Playgroud)

编辑:我做了一些测试,似乎使用numpy.arraynumpy.ndarray作为矢量太慢.(例如,获取一个项目需要几乎两倍的长度,更不用说创建一个数组.我认为它更适合于对大量项目进行计算.)

所以,我正在寻找一个轻量级的矢量类,它具有固定数量的字段(在我的情况下只是xy),可以用于游戏.(如果已经有一个经过充分测试的车轮,我不想重新发明轮子.)

Eri*_*got 16

是的,有一个矢量类:它在事实上的标准NumPy模块中.你创建这样的矢量:

>>> v = numpy.array([1, 10, 123])
>>> 2*v
array([  2,  20, 246])
>>> u = numpy.array([1, 1, 1])
>>> v-u
array([  0,   9, 122])
Run Code Online (Sandbox Code Playgroud)

NumPy非常丰富,可让您访问快速数组操作:dot product(numpy.dot()),norm(numpy.linalg.norm())等.


ask*_*han 5

就线性代数而言的向量numpy可能numpy.matrix是 的子类numpy.ndarray。它本身并不干净但它使您的代码更干净,因为假定代数运算而不是元素运算。

In [77]: a = np.array([1,2])

In [78]: b = np.array([3,3])

In [79]: a*b
Out[79]: array([3, 6])

In [80]: np.dot(a,b)
Out[80]: 9

In [81]: np.outer(a,b)
Out[81]: 
array([[3, 3],
       [6, 6]])

In [82]: a = np.matrix(a).T

In [83]: b = np.matrix(b)

In [84]: b*a
Out[84]: matrix([[9]])

In [85]: a*b
Out[85]: 
matrix([[3, 3],
        [6, 6]])
Run Code Online (Sandbox Code Playgroud)

如果您想创建自己的,请基于其中之一,例如:

class v2d(np.ndarray):
    def __abs__(self):
        return np.linalg.norm(self)
    def dist(self,other):
        return np.linalg.norm(self-other)
    def dot(self, other):
        return np.dot(self, other)
    # and so on
Run Code Online (Sandbox Code Playgroud)

在最简单的情况下,您只需将 anndarray视为新类即可:

In [63]: a = np.array([1,2]).view(v2d)

In [64]: b = np.array([3,3]).view(v2d)

In [65]: a
Out[65]: v2d([1, 2])

In [66]: abs(b)
Out[66]: 4.2426406871192848

In [67]: a - b
Out[67]: v2d([-2, -1])

In [68]: a*b
Out[68]: v2d([3, 6])

In [69]: a*3
Out[69]: v2d([3, 6]) 

In [70]: a.dist(b)
Out[70]: 2.2360679774997898

In [71]: b.dist(a)
Out[71]: 2.2360679774997898

In [72]: a.dot(b)
Out[72]: 9
Run Code Online (Sandbox Code Playgroud)

这是有关子类化ndarray.