Ich habe eine Python-Anwendung, die wie folgt lautet:
global_counter = 0
connections = {}
class SocketHandler():
currentid = 0
def open(self):
global global_counter
global connections
currentid = global_counter
global_counter += 1
connections[currentid] = self
print "WebSocket " + str(currentid) + " opened"
def on_close(self):
global connections
print "WebSocket " + str(currentid) + " closed"
del connections[currentid]
Ich erhalte den Fehler:
NameError: global name 'currentid' is not defined
In den Zeilen "open" und "on_close", in denen ich drucke, dass ich die Verbindung öffne / schließe. Ich habe es in der Klasse definiert, warum ist es nicht im Umfang. Ich habe auch gelesen, dass die Verwendung globaler Variablen schlecht ist, aber ich sehe keinen Weg, dies zu umgehen. Kann jemand darauf hinweisen, was ich tun soll? Vielen Dank.
3 Antworten
Sie haben in Python keinen impliziten Zugriff auf Attribute in Methoden.
Ein nackter Name wie currentid
in der Zeile:
del connections[currentid]
Sucht immer nach einem Namen im lokalen Funktionsbereich und dann in jedem umschließenden Funktionsbereich, bevor der globale Modulbereich ausprobiert wird (und betrachtet dann die integrierten Funktionen als letzten Ausweg). currentid
ist ein Klassenattribut, das in keinem dieser Bereiche gefunden wird.
Um ein Attribut in Python nachzuschlagen, müssen Sie immer ein Objekt angeben, in dem gesucht werden soll. Obwohl das Suchprotokoll bedeutet, dass das Objekt nicht unbedingt das Attribut selbst haben muss; Die Attributsuche greift auf die Klasse des von Ihnen angegebenen Objekts zurück (und auf die Basisklassen, wenn die Vererbung betroffen ist).
Das würde also funktionieren:
del connections[self.currentid]
Ich glaube jedoch nicht, dass der Rest Ihres Codes das tut, was Sie denken. Diese Zeile in der Methode open
:
currentid = global_counter
Setzt das currentid
-Attribut Ihres SocketHandler
-Objekts nicht. Zuweisen zu einem bloßen Namen immer wird einer lokalen Variablen zugewiesen, es sei denn, Sie deklarieren sie explizit als global
(Sie scheinen sich dessen bewusst zu sein, da Sie das Schlüsselwort global
verwendet haben ). In der open
-Methode ist currentid
also eine lokale Funktionsvariable. Sein Wert geht am Ende der open
-Methode verloren.
Tatsächlich haben Ihre SocketHandler
Objekte überhaupt kein currentid
-Attribut (es sei denn, es gibt mehr Code, den Sie uns nicht gezeigt haben). Wenn Sie currentid = 0
in den Klassenblock einfügen, erhalten nicht alle SocketHandler
Instanzen ein currentid
-Attribut. Es gibt der SocketHandler
Klasse selbst ein Attribut currentid
; Dies ist genau so, wie der def open(self):
-Block ein open
-Attribut (Speichern einer Funktion) für das Klassenobjekt erstellt, nicht für jede einzelne Instanz.
Wenn Sie self.currentid
in der on_close
-Methode lesen, wird kein currentid
-Attribut im Objekt self
gefunden, sodass Python die Klasse von self
betrachtet, die {ist {X5}}. Dieses Objekt hat einen Wert von currentid
, sodass das Ergebnis des Lesens von self.currentid
0
ist, unabhängig davon, ob Sie zuvor open
ausgeführt haben oder nicht. auf diesem SocketHandler
.
Wenn Sie currentid
als Instanzvariable in jedem SocketHandler
speichern möchten, muss die Zeile in open
wie folgt lauten:
self.currentid = global_counter
Dies wird dem Attribut currentid
des Objekts zugewiesen, auf das self
verweist. Sie müssten dann auch alle anderen Verweise auf currentid
in Ihren Methoden in self.currentid
ändern.
currentid
ist ein Instanzattribut. Verwenden Sie daher self.currentid
anstelle von currentid
:
def on_close(self):
global connections
print "WebSocket " + str(self.currentid) + " closed"
del connections[self.currentid]
currentid
sollte self.currentid
sein, da es sich um eine Klassenvariable handelt.
Verwandte Fragen
Neue Fragen
python
Python ist eine dynamisch typisierte Mehrzweck-Programmiersprache mit mehreren Paradigmen. Es wurde entwickelt, um schnell zu lernen, zu verstehen, zu verwenden und eine saubere und einheitliche Syntax durchzusetzen. Bitte beachten Sie, dass Python 2 ab dem 01.01.2020 offiziell nicht mehr unterstützt wird. Fügen Sie für versionenspezifische Python-Fragen das Tag [python-2.7] oder [python-3.x] hinzu. Wenn Sie eine Python-Variante (z. B. Jython, PyPy) oder eine Bibliothek (z. B. Pandas und NumPy) verwenden, fügen Sie diese bitte in die Tags ein.