Extremely slow object creation in Python 2.7

Recently, I had to complete a task that used many operations with coordinates. Thinking to save time and simplify my code, I defined a class for encapsulating the behavior of a pair of coordinates. 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 tasks. I could not find any inefficiency in my implementation of the algorithm, so I did a simple test to find out what the overhead of the Vector class is. I was expecting somewhere between 5% and 15%.

My Vector class test looked like this:

 v = Vector ((0, 0)) d = Vector ((1, -1)) loopIdx = 3000000 while loopIdx > 0 : v = v + d loopIdx -= 1 print (v) 

This executes (usually) at this type 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) 

Runtime for this code:

 real 0m1.004s user 0m0.995s sys 0m0.006s 

Am I doing something serious wrong, or does using class objects in Python really mean that your application will take 8 times as long?

+6
source share
1 answer

Not quite the answer, how to make your class faster, but more alternatives.

Instead of subclassing tuple and for writing all of these add , sub methods, etc. you just use the Python bultin complex type for 2D coordinates, which has all the operations that have already been built in, correctly and superfast.

 >>> %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 

For rotation, you can use complex multiplication: just multiply your complex coordinate by a complex number, which in polar form has an absolute value of 1 and a phase equal to the angle you want to rotate. To rotate 90 degrees, you can simply multiply by 1j (counterclockwise) or -1j (clockwise). For all other angles, use the cmath module to translate to and from the polar form.

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

However, I would suggest not to subclass complex to make the rotate method of this class, because in this case you will have to rewrite all the other methods, for example add , otherwise the result of the addition will be a regular complex number that does not provide the rotate method. And that will undo all these performance gains, making it as slow as your Vector class. Instead, just create a function rotate(complex, angle) -> complex .

+1
source

Source: https://habr.com/ru/post/989805/


All Articles