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 является атрибутом экземпляра, поэтому используйте self.currentid вместо currentid:

def on_close(self):
        global connections
        print "WebSocket " + str(self.currentid) + " closed"
        del connections[self.currentid]