Ich habe Python-Klassen, von denen ich zur Laufzeit nur eine Instanz benötige. Es würde also ausreichen, die Attribute nur einmal pro Klasse und nicht pro Instanz zu haben. Wenn es mehr als eine Instanz geben würde (was nicht passieren wird), sollten alle Instanzen dieselbe Konfiguration haben. Ich frage mich, welche der folgenden Optionen besser oder "idiomatischer" Python wäre.
Klassenvariablen:
class MyController(Controller):
path = "something/"
children = [AController, BController]
def action(self, request):
pass
Instanzvariablen:
class MyController(Controller):
def __init__(self):
self.path = "something/"
self.children = [AController, BController]
def action(self, request):
pass
Antworten:
Wenn Sie ohnehin nur eine Instanz haben, ist es am besten, alle Variablen pro Instanz zu erstellen, einfach weil auf sie (ein wenig) schneller zugegriffen wird (eine Stufe weniger "Nachschlagen" aufgrund der "Vererbung" von Klasse zu Instanz). und es gibt keine Nachteile, die gegen diesen kleinen Vorteil abgewogen werden könnten.
quelle
python -mtimeit
- aber nachdem ich dies gerade in Python3.4 getan habe, stelle ich fest, dass der Zugriff auf eineint
Klassenvariable tatsächlich etwa 5 bis 11 Nanosekunden schneller ist als die Instanzvariable auf meiner alten Workstation - nicht sicher, was Codepath macht es so.Weiteres Echo von Mike und Alex Ratschläge von und Hinzufügen meiner eigenen Farbe ...
Die Verwendung von Instanzattributen ist das typische ... das idiomatischere Python. Klassenattribute werden nicht so häufig verwendet, da ihre Anwendungsfälle spezifisch sind. Gleiches gilt für statische und Klassenmethoden im Vergleich zu "normalen" Methoden. Es handelt sich um spezielle Konstrukte, die sich mit bestimmten Anwendungsfällen befassen. Andernfalls handelt es sich um Code, der von einem abweichenden Programmierer erstellt wurde, der zeigen möchte, dass er eine dunkle Ecke der Python-Programmierung kennt.
Alex erwähnt in seiner Antwort, dass der Zugriff aufgrund einer geringeren Nachschlageebene (ein wenig) schneller sein wird. Lassen Sie mich diejenigen näher erläutern, die noch nicht wissen, wie dies funktioniert. Es ist dem variablen Zugriff sehr ähnlich - die Suchreihenfolge lautet:
Für den Attributzugriff lautet die Reihenfolge:
Beide Techniken arbeiten "von innen nach außen", dh die meisten lokalen Objekte werden zuerst überprüft, dann werden die äußeren Schichten nacheinander überprüft.
Angenommen, Sie suchen in Ihrem obigen Beispiel nach dem
path
Attribut. Wenn es auf eine Referenz wie "self.path
Python " , überprüft Python zuerst die Instanzattribute auf Übereinstimmung. Wenn dies fehlschlägt, wird die Klasse überprüft, aus der das Objekt instanziiert wurde. Schließlich werden die Basisklassen durchsucht. Wie Alex sagte, muss Ihr Attribut, wenn es in der Instanz gefunden wird, nicht woanders gesucht werden, daher sparen Sie ein wenig Zeit.Wenn Sie jedoch auf Klassenattributen bestehen, benötigen Sie diese zusätzliche Suche. Oder Ihre andere Alternative besteht darin, über die Klasse anstelle der Instanz auf das Objekt zu verweisen, z. B.
MyController.path
anstelle vonself.path
. . Dies ist eine direkte Suche, die die verzögerte Suche umgeht. Wie Alex weiter unten erwähnt, handelt es sich jedoch um eine globale Variable. Sie verlieren also das Bit, von dem Sie dachten, dass Sie es speichern würden (es sei denn, Sie erstellen einen lokalen Verweis auf den [globalen] Klassennamen ).Unter dem Strich sollten Sie die meiste Zeit Instanzattribute verwenden. Es wird jedoch Fälle geben, in denen ein Klassenattribut das richtige Werkzeug für den Job ist. Code, der beide gleichzeitig verwendet, erfordert die größte Sorgfalt, da bei Verwendung
self
nur das Instanzattributobjekt und der Schattenzugriff auf das gleichnamige Klassenattribut verfügbar sind. In diesem Fall Sie müssen das Attribut durch die Klassennamen , um es zu verweisen zugreifen.quelle
MyController
wird aber in den Globals nachgeschlagen, sodass die Gesamtkosten höher sind alsself.path
beipath
einer Instanzvariablen (da die Methode == superschnelle Suche lokalself
ist ).Im Zweifelsfall möchten Sie wahrscheinlich ein Instanzattribut.
Klassenattribute sind am besten für Sonderfälle reserviert, in denen sie sinnvoll sind. Der einzige sehr häufige Anwendungsfall sind Methoden. Es ist nicht ungewöhnlich , Klassenattribute für schreibgeschützte Konstanten zu verwenden, die Instanzen kennen müssen (obwohl der einzige Vorteil darin besteht, dass Sie auch von außerhalb der Klasse zugreifen möchten ), aber Sie sollten auf jeden Fall vorsichtig sein, wenn Sie einen Status in ihnen speichern , was selten ist, was Sie wollen. Selbst wenn Sie nur eine Instanz haben, sollten Sie die Klasse wie jede andere schreiben, was normalerweise die Verwendung von Instanzattributen bedeutet.
quelle
avoid global variables
und ihre Definition ist, dass globale Variablen auch Variablen sind, die als Klassenattribute deklariert werden. Pythons eigener Styleguide ( PEP-8 ) sollte jedoch der erste Ort sein, an dem Fragen dieser Art beantwortet werden. Dann sollte Ihr eigener Verstand das Werkzeug der Wahl sein (natürlich können Sie auch Ideen von Google erhalten).Gleiche Frage bei Leistung beim Zugriff auf Klassenvariablen in Python - der hier von @Edward Loper angepasste Code
Lokale Variablen sind am schnellsten zugänglich, da sie weitgehend mit Modulvariablen verknüpft sind, gefolgt von Klassenvariablen, gefolgt von Instanzvariablen.
Es gibt 4 Bereiche, in denen Sie auf Variablen zugreifen können:
Der Test:
Das Ergebnis:
quelle