Переменная класса Python из вхождения подкласса - PullRequest
1 голос
/ 25 октября 2019

Рассмотрим этот код

class A:
    class B:
        foo = 1
    bar = {x: B for x in range(5)}

Это приведет к ошибке о том, что B не определено. Однако, останавливаясь с отладчиком на соответствующей строке в REPL, я могу нормально выполнить этот код. Кажется, это какая-то проблема с вложенностью / областью видимости, но я ее не понимаю.

Может кто-нибудь объяснить, что происходит и, возможно, как обойти это?

1 Ответ

3 голосов
/ 25 октября 2019

Диктовое понимание неявно определяет анонимную функцию. В теле этой функции B является свободной переменной. Правила поиска переменных гласят, что значение B берется из ближайшей охватывающей области, которая определяет B, , но a class инструкция не определяет область действия (хотя она и определяет временнуюпространство имен, которое похоже на правильную область видимости). Следующей областью по сравнению с локальной областью действия анонимной функции является глобальная область, где B не определено.

Чтобы избежать проблемы с привязкой, определите функцию, которая принимает B в качестве аргумента, и получитефункция выполняет понимание dict:

bar = (lambda cls: {x: cls for x in range(5)})(B)

Теперь B is можно найти в текущем пространстве имен оператора class (правила области видимости исключаются), а cls, определяемого вобласть действия анонимной функции, определяемой лямбда-выражением, теперь может быть найдена в стеке областей, используемых в понимании dict. Иными словами, анонимная функция, создаваемая пониманием, является замыканием области действия функции лямбда-выражения.

Тем не менее, вложенные классы на самом деле не распространены в Python;Вы можете определить B в глобальном масштабе, чтобы решить проблему в этом случае.

...