Python 2.7中极慢的对象实例化

Ter*_*ole 6 python performance overhead python-2.7

我最近不得不完成一项使用了大量坐标操作的任务.为了节省时间并简化我的代码,我定义了一个类来封装坐标对的行为.这堂课看起来像这样:

class Vector (tuple) :
    def __init__ (self, value) :
        tuple.__init__ (self, value)


    def __add__ (self, other) :
        return Vector ((self [0] + other [0], self [1] + other [1]))
Run Code Online (Sandbox Code Playgroud)

这允许我编写这样的代码(例如):

def translate (pointList, displacement) :
    return [point + displacement for point in pointList]
Run Code Online (Sandbox Code Playgroud)

但我的申请非常缓慢.比其他任务慢得多.我找不到算法实现中的任何低效率,所以我做了一个简单的测试来看看Vector类的开销是多少.我预计在5%到15%之间.

我对Vector类的测试看起来像这样:

v = Vector ((0, 0))
d = Vector ((1, -1))
loopIdx = 3000000
while loopIdx > 0 :
    v = v + d
    loopIdx -= 1
print (v)
Run Code Online (Sandbox Code Playgroud)

这种情况(通常)在这种情况下运行:

real    0m8.440s
user    0m8.367s
sys     0m0.016s
Run Code Online (Sandbox Code Playgroud)

为了比较我运行了这段代码:

v = (0, 0)
dX = 1
dY = -1
loopIdx = 3000000
while loopIdx > 0 :
    v = ( v [0] + dX, v [1] + dY )
    loopIdx -= 1
print (v)
Run Code Online (Sandbox Code Playgroud)

此代码的运行时间为:

real    0m1.004s
user    0m0.995s
sys     0m0.006s
Run Code Online (Sandbox Code Playgroud)

我做错了什么,或者在Python中使用类对象真的意味着你的应用程序需要花费8倍的时间来运行吗?

tob*_*s_k 1

并不是真正的答案如何让你上课更快,而是更多的选择。

您不必自己子类化和tuple编写所有这些等方法,而是只需使用 Python 的2D 坐标的布尔数字类型,它已经内置了所有这些操作,正确且超快。addsubcomplex

>>> %timeit vector_no_init()
1 loops, best of 3: 1.39 s per loop
>>> %timeit plain_tuple()
1 loops, best of 3: 403 ms per loop
>>> %timeit complex_nums()
1 loops, best of 3: 171 ms per loop
Run Code Online (Sandbox Code Playgroud)

对于旋转,您可以使用复数乘法:只需将复数坐标与一个复数相乘,该复数的极坐标形式的绝对值为 1,相位等于您要旋转的角度。要旋转 90 度,只需乘以1j(逆时针)或-1j(顺时针)即可。对于所有其他角度,请使用该cmath模块在极坐标形式之间进行转换。

>>> c = complex(4, 2)
>>> c * cmath.rect(1, math.radians(45))
(1.4142135623730954+4.242640687119285j)
Run Code Online (Sandbox Code Playgroud)

但是,我建议不要子类化complex以创建rotate该类的方法,因为在这种情况下,您将必须覆盖所有其他方法,例如add, ,否则加法的结果将是一个常规复数,而不提供rotate方法。这会抵消所有这些性能提升,使其与你的Vector类一样慢。相反,只需创建一个函数即可rotate(complex, angle) -> complex