NameError ссылается на переменные класса в понимании - PullRequest
1 голос
/ 24 февраля 2020

Я получаю NameError: name 'ID' is not defined, когда пытаюсь получить доступ к переменной класса в понимании dict, например, в class A. При ссылках без понимания это работает нормально (см. class B). Итак, мой вопрос: почему он генерирует NameError в классе A, но не в классе B?

class A:
    ID = "This is class A."

    test = {str(i): ID for i in range(5)}

class B:
    ID = "This is class B."

    test = f"{ID}"

1 Ответ

0 голосов
/ 24 февраля 2020

Примечание по разрешению имен в Python:

Блоки определения класса и аргументы для exec() и eval() являются особыми в контексте разрешения имен. Определение класса - это исполняемый оператор, который может использовать и определять имена. Эти ссылки следуют обычным правилам разрешения имен, за исключением того, что несвязанные локальные переменные ищутся в глобальном пространстве имен. Пространство имен определения класса становится словарем атрибутов класса. Область имен, определенных в блоке класса, ограничена блоком класса; он не распространяется на блоки кода методов - это включает в себя понимания и выражения генератора, поскольку они реализованы с использованием области действия функции. Это означает, что произойдет сбой следующего:

Вы определили переменную ID внутри определения класса, которая делает ее переменной class или static. Таким образом, область действия ограничена блоком класса , и, следовательно, вы не можете получить к нему доступ внутри comprehensions.

. Подробнее об этом можно прочитать в python документах.

Рассмотрим примеры,

Пример # 1:

class A:
    ID = "This is class A."
    print(ID)

Теперь, когда вы выполните >>>A(), вывод будет This is class A, что совершенно нормально, поскольку область действия переменной ID ограничена классом A


Пример № 2:

class B:
    L = [ 1, 2, 3, 4, 5, 6, 7]
    print([i * 2 for i in L])

Сейчас при выполнении >>>B() вывод будет [2, 4, 6, 8, 10, 12, 14], что вполне нормально, поскольку область действия списка L ограничена классом B


Пример № 3:

class C:
   L = [ 1, 2, 3, 4, 5, 6, 7]
   print([L[i] * 2 for i in range(7)])

Теперь выполнение >>>C() вызовет NameError, заявив, что имя L не определено.

...