I recently had to complete an assignment that used a lot of coordinate operations. Thinking to save time and simplify my code, I defined a class to encapsulate the behaviour of a coordinate pair. The class looked like this:
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]))
This allowed me to write code like this (for example):
def translate (pointList, displacement) :
return [point + displacement for point in pointList]
But my application was terribly slow. Much slower than other assignments. I couldn't locate any inefficiency in my implementation of the algorithm, so I did a simple test to see what the overhead was of the Vector class. I expected somewhere between 5% and 15%.
My test of the Vector class looked like this:
v = Vector ((0, 0))
d = Vector ((1, -1))
loopIdx = 3000000
while loopIdx > 0 :
v = v + d
loopIdx -= 1
print (v)
This runs (typically) in this kind of time:
real 0m8.440s
user 0m8.367s
sys 0m0.016s
For comparison I ran this code:
v = (0, 0)
dX = 1
dY = -1
loopIdx = 3000000
while loopIdx > 0 :
v = ( v [0] + dX, v [1] + dY )
loopIdx -= 1
print (v)
Run time for this code is:
real 0m1.004s
user 0m0.995s
sys 0m0.006s
Have I done something seriously wrong, or does using class objects in Python really mean your application will take over 8 times as long to run?
Not really an answer how to make you class faster, but more of an alternative.
Instead of subclassing
tuple
and writing all thoseadd
,sub
etc. methods yourself, you cold just use Python's bultincomplex
number type for 2D coordinates, which has all those operations already built in, correct and and super-fast.For rotation, you can use complex multiplication: Just multiply your complex coordinate with a complex number that has, in polar form, absolute value 1 and a phase equal to the angle you want to rotate by. To rotate by 90 degrees, you can just multiply by
1j
(anti-clockwise) or-1j
(clockwise). For all other angles, use thecmath
module for translation to and from polar form.However, I would suggest not to subclass
complex
to makerotate
a method of that class, because in this case you will have to overwrite all the other methods, likeadd
, as well, otherwise the result of addition will be a regular complex number, not providing therotate
method. And this would undo all those performance gains, making it just as slow as yourVector
class. Instead, just make a functionrotate(complex, angle) -> complex
.