Используйте файл Python в качестве пространства имен

#python #class #namespaces #function-definition

Вопрос:

Я столкнулся с проблемой, которая кажется тривиальной.

Если мы определим такую структуру в файле python:

 class A:
   pass

class B:
   a = A()
 

Мы не можем определить это по-другому:

 class B:
   a = A  # <-- the error is here

class A:
   pass
 

Компилятор говорит a = A , что это неразрешенная ссылка, но мы делаем это, java например, в «все в порядке», и она будет скомпилирована.

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

Может python ли файл быть преобразован в пространство имен, аналогично функциям внутри класса, которые знают об их существовании, независимо от последовательности их определения?

Комментарии:

1. В случае вашей ошибки: a = A оценивается немедленно, так как это атрибут класса. В этот момент интерпретатор еще не создан class A , поэтому вы получаете ошибку.

2. При a = A выполнении Python будет использовать объект A , на который ссылается в данный момент. Вы определяете класс A позже в своем коде, но нет никакой гарантии, что имя A не будет ссылаться на какой-либо другой объект в какой-то момент во время выполнения вашего сценария. Таким образом, единственная логичная вещь-использовать текущее значение и выдавать ошибку, если оно еще не задано.

3. Python-это не Java. Хотя обратите внимание, что в Python код также компилируется . Проблема в том, что в Python тела классов, как и любая другая часть кода, выполняются, а тело используется в качестве пространства имен для класса (вы можете думать об этом как о синтаксическом сахаре для вызова конструктора объектов класса (типа) , type(name, (parents,), namespace)

4. «Может ли файл python быть преобразован в пространство имен» модуль уже действует как пространство имен. Я не понимаю, что вы имеете в виду под этим.

5. Если быть точным, вы не можете сделать это в теле инструкции определения класса , если определение класса B стоит на первом месте. Вы всегда можете сделать B.a = A() это после определения A , если вы настаиваете на определении своих классов в таком порядке