#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
, если вы настаиваете на определении своих классов в таком порядке