Python-почему эта переменная класса не определена в методе?
у меня есть приложение python, которое выглядит следующим образом:
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]
Я получаю ошибку:
NameError: global name 'currentid' is not defined
в строках "открыть" и "on_close", где я печатаю, что я открываю/закрываю соединение. Я определил его в классе, почему он не в рамках. Кроме того, я читал, что использование глобальных переменных плохо, но я не вижу способа обойти это. Кто-нибудь может указать, что мне делать? Спасибо.
3 ответов
у вас нет неявного доступа к атрибутам внутри методов в Python.
голое имя, как currentid
в строку:
del connections[currentid]
всегда ищет имя в локальной области функций, затем в каждой области функций, прежде чем пытаться использовать глобальную область модуля (а затем смотрит на встроенные модули в качестве последнего средства). currentid
- это атрибут класса, который не будет найден ни в одной из этих областей.
чтобы найти атрибут в Python, вы всегда необходимо указать объект, в котором нужно искать. Хотя протокол поиска означает, что объект не обязательно должен иметь сам атрибут; поиск атрибута будет возвращаться к классу указанного вами объекта (и базовым классам, если задействовано наследование).
так что это сработает:
del connections[self.currentid]
однако я не думаю, что остальная часть вашего кода делает то, что вы думаете. Эта строка в open
метод:
currentid = global_counter
нет вашего . Это дает SocketHandler
класс атрибут currentid
; это так же, как def open(self):
блок создает open
атрибут (хранение функции) на объекте класса, а не на каждом отдельном экземпляре.
чтение self.currentid
на on_close
метод не сможет найти currentid
атрибут в объекте self
, так Python будет смотреть на класс self
что это SocketHandler
. Этот объект!--56-->тут есть currentid
значение, поэтому результат чтения self.currentid
будет 0
, независимо от того, выполняли ли вы ранее open
на SocketHandler
.
если вы намеревались хранить currentid
как переменная экземпляра в каждом SocketHandler
, то в строке open
должно быть:
self.currentid = global_counter
это присваивает currentid
атрибут объекта, на который ссылается self
. Вы бы также необходимо изменить все остальные ссылки на currentid
в ваших методах self.currentid
.
currentid
является атрибутом экземпляра, поэтому используйте self.currentid
вместо currentid
:
def on_close(self):
global connections
print "WebSocket " + str(self.currentid) + " closed"
del connections[self.currentid]