Доступ к явно неопределенной переменной Python? [Дубликат]

ДА

... при условии, что существует некоторое максимальное количество гнезд, с которыми вы были бы счастливы остановиться.

Позвольте мне объяснить.


@ torsten-marek прав, что регулярное выражение не может проверять вложенные шаблоны, подобные этому, но возможно определить вложенный шаблон регулярного выражения, который позволит вам захватите вложенные структуры, подобные этому , до некоторой максимальной глубины . Я создал один, чтобы записать комментарии в формате EBNF ( попробуйте здесь ), например:

(* This is a comment (* this is nested inside (* another level! *) hey *) yo *)

Регулярное выражение (для комментариев с одной глубиной ) является следующим:

m{1} = \(+\*+(?:[^*(]|(?:\*+[^)*])|(?:\(+[^*(]))*\*+\)+

Это может быть легко адаптировано для ваших целей, заменив \(+\*+ и \*+\)+ на { и } и заменив все между простыми [^{}]:

p{1} = \{(?:[^{}])*\}

( Вот ссылка , чтобы попробовать это.)

Чтобы вложить, просто разрешите этот шаблон внутри самого блока:

p{2} = \{(?:(?:p{1})|(?:[^{}]))*\}
  ...or...
p{2} = \{(?:(?:\{(?:[^{}])*\})|(?:[^{}]))*\}

Чтобы найти тройные вложенные блоки, используйте:

p{3} = \{(?:(?:p{2})|(?:[^{}]))*\}
  ...or...
p{3} = \{(?:(?:\{(?:(?:\{(?:[^{}])*\})|(?:[^{}]))*\})|(?:[^{}]))*\}

Появился четкий шаблон. Чтобы найти комментарии, вложенные в глубину N, просто используйте регулярное выражение:

p{N} = \{(?:(?:p{N-1})|(?:[^{}]))*\}

  where N > 1 and
  p{1} = \{(?:[^{}])*\}

Сценарий можно записать для рекурсивного генерации этих регулярных выражений, но это выходит за рамки того, для чего мне это нужно. (Это остается как упражнение для читателя.

6
задан Lylax 8 October 2012 в 23:03
поделиться

3 ответа

У вас нет неявного доступа к атрибутам внутри методов в Python.

Голова имя типа currentid в строке:

del connections[currentid]

всегда ищет имя в области локальных функций, затем в каждой области охватывающей функции, перед тем, как попробовать глобальную область модуля (а затем посмотрите на встроенные вложения в качестве последнего средства). currentid - это атрибут класса, который не будет найден ни в одном из этих областей.

Чтобы найти атрибут в Python, вам всегда нужно указать объект для просмотра. Хотя протокол поиска означает, что объект необязательно должен иметь сам атрибут; поиск атрибута вернется к классу указанного вами объекта (и базовые классы, если наследование задействовано).

Итак, это сработает:

del connections[self.currentid]

Однако I не думайте, что остальная часть вашего кода делает то, что вы думаете. Эта строка в методе open:

currentid = global_counter

не устанавливает атрибут currentid вашего объекта SocketHandler. При назначении головому имени всегда присваивает локальную переменную, если вы явно не объявляете ее global (вы, похоже, знаете об этом, так как вы использовали ключевое слово global). Таким образом, в методе open currentid является локальной переменной функции; его значение теряется в конце метода open.

На самом деле, ваши SocketHandler объекты вообще не имеют атрибута currentid (если только нет кода, который вы нам не показали ). Помещение currentid = 0 в блок класса не дает всем экземплярам SocketHandler атрибуту currentid. Это дает SocketHandler класс самому атрибуту currentid; это так же, как блок def open(self): создает атрибут open (сохраняющий функцию) для объекта класса, а не для каждого отдельного экземпляра.

Чтение self.currentid в методе on_close не будет выполнено найти атрибут currentid в объекте self, поэтому Python будет смотреть на класс self, который является SocketHandler. Этот объект имеет значение currentid, поэтому результат чтения self.currentid будет 0, независимо от того, вы ранее выполняли open на этом SocketHandler.

Если вы хотели сохранить currentid в качестве переменной экземпляра в каждом SocketHandler, тогда строка в open должна быть:

self.currentid = global_counter

Это назначает currentid атрибута объекта, на который ссылается self. Вам также потребуется изменить все остальные ссылки на currentid в ваших методах на self.currentid.

9
ответ дан Ben 20 August 2018 в 20:06
поделиться
  • 1
    Это действительно прояснило, спасибо, что написал это. – Lylax 8 October 2012 в 23:45

currentid - атрибут экземпляра, поэтому используйте self.currentid вместо currentid:

def on_close(self):
        global connections
        print "WebSocket " + str(self.currentid) + " closed"
        del connections[self.currentid]
0
ответ дан defuz 20 August 2018 в 20:06
поделиться

currentid должен быть self.currentid, поскольку это переменная класса.

3
ответ дан ronak 20 August 2018 в 20:06
поделиться
  • 1
    Это имеет смысл, спасибо! – Lylax 8 October 2012 в 23:07
  • 2
    Почему это так много? - код в приведенном выше примере больше не будет ломаться с NameError, но будет ломаться с серьезной логической ошибкой, если будет произведена только эта замена. – jsbueno 8 October 2012 в 23:08
  • 3
    @jsbueno: Что ты имеешь в виду? Единственными изменяемыми переменными являются глобальные переменные. – Blender 8 October 2012 в 23:13
  • 4
    @Blender Насколько вероятен, по вашему мнению, что OP должен иметь локальную переменную с тем же именем, что и атрибут класса внутри метода open? И всегда ли on_close метод del connections[0]? – Ben 8 October 2012 в 23:23
  • 5
    @Ben: Извините, я прочитал комментарий jsbueno, сказав, что в скрипте будет ошибка синтаксического анализа, а не ошибка времени выполнения. – Blender 8 October 2012 в 23:28
Другие вопросы по тегам:

Похожие вопросы: