2015-06-26 7 views
6

Ich musste vor kurzem eine Aufgabe abschließen, die viele Koordinatenoperationen verwendet. Um Zeit zu sparen und meinen Code zu vereinfachen, habe ich eine Klasse definiert, die das Verhalten eines Koordinatenpaars kapselt. Die Klasse sah wie folgt aus:Extrem langsame Objekt Instanziierung in 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])) 

Das bin ich Code wie diesen schreiben erlaubt (zum Beispiel):

def translate (pointList, displacement) : 
    return [point + displacement for point in pointList] 

Aber meine Anwendung war schrecklich langsam. Viel langsamer als andere Aufgaben. Ich konnte in meiner Implementierung des Algorithmus keine Ineffizienz feststellen, also habe ich einen einfachen Test durchgeführt, um zu sehen, wie hoch der Overhead der Vector-Klasse ist. Ich habe irgendwo zwischen 5% und 15% erwartet.

Mein Test der Vector-Klasse sah wie folgt aus:

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

Dies läuft (in der Regel) in dieser Art von Zeit:

real 0m8.440s 
user 0m8.367s 
sys  0m0.016s 

Zum Vergleich lief ich diesen Code:

v = (0, 0) 
dX = 1 
dY = -1 
loopIdx = 3000000 
while loopIdx > 0 : 
    v = (v [0] + dX, v [1] + dY) 
    loopIdx -= 1 
print (v) 

Laufzeit für diesen Code ist:

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

Habe ich etwas ernsthaft falsch gemacht, oder bedeutet die Verwendung von Klassenobjekten in Python wirklich, dass Ihre Anwendung 8 Mal so lange dauert, um ausgeführt zu werden?

+0

Es ist wahrscheinlich nicht die Klasse selbst, mehr Tuple wird direkt in C implementiert, während Ihre Klasse nicht ist. –

+1

Keine Antwort auf die Frage, aber: Statt Ihrer 'Vector' Klasse könnten Sie einfach' komplexe' Zahlen zur Darstellung von 2D Koordinaten verwenden. Addition, Substration, absoluter Wert (für Entfernung) etc. enthalten.Auch das ist 2-3 Mal schneller als mit Tupeln wie in Ihrem zweiten Ansatz. –

+1

Sie könnten eine Klasse mit '__slots__' in Betracht ziehen, um den Speicherbedarf jeder Instanz zu minimieren. – jonrsharpe

Antwort

1

Nicht wirklich eine Antwort wie Sie Ihre Klasse schneller machen, aber eher eine Alternative.

Statt Subklassifizieren tuple und Schreiben alle add, sub usw. Methoden selbst, kalt Sie nur bultin complex Nummer Typ des Python für 2D-Koordinaten, die diese Vorgänge bereits eingebaut alles hat, richtig und und super-schnell.

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

Für Rotation können Sie komplexe Multiplikation verwenden: Just multiplizieren Sie Ihre Anlage mit einer komplexen Zahl koordinieren, die Sie in polarer Form, Absolutwert 1 und einer Phase gleich dem Winkel ist, durch drehen möchten. Um um 90 Grad zu drehen, können Sie einfach durch 1j (gegen den Uhrzeigersinn) oder -1j (im Uhrzeigersinn) multiplizieren. Für alle anderen Winkel verwenden Sie das cmath Modul für die Übersetzung in und von der Polarform.

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

Allerdings würde ich vorschlagen nicht complex Unterklasse rotate ein Verfahren zur Herstellung dieser Klasse zu machen, denn in diesem Fall werden Sie alle anderen Methoden überschreiben müssen, wie add, als auch, sonst das Ergebnis der Addition wird eine reguläre komplexe Zahl sein, die rotate Methode nicht zur Verfügung stellt. Und das würde all diese Leistungssteigerungen zunichte machen und es genauso langsam machen wie Ihre Vector Klasse. Stellen Sie stattdessen einfach eine Funktion rotate(complex, angle) -> complex.

+0

Danke. Als vorläufiges Ergebnis führt die Verwendung von "complex" zum Ersetzen der Tuple-Roharithmetik (keine Klasse) zu einer Leistungsverbesserung von 40%. –