Ответ «только потому что».
Он не имеет ничего общего с системой типов Python или динамическим. Это связано с порядком, в котором инициализируется новый введенный тип.
Несколько месяцев назад я разработал систему объекта для языка TxR, в котором это работает:
1> (defstruct foo nil (:static bar (new foo)))
#
2> (new foo)
#S(foo)
3> *2.bar
#S(foo)
Здесь bar
статический слот («переменная класса») в foo
. Он инициализируется выражением, которое создает foo
.
Почему это работает можно понять из function-based API для конкретизации нового типа, где инициализация статического класса выполняется с помощью функции, которая передается в. defstruct
макросъемки составляет вызов make-struct-type
, в котором выражение концы (new foo)
вверх в теле анонимной функции, которая передается для аргумента static-initfun . Эта функция вызывается после того, как тип уже зарегистрирован под символом foo
.
Мы могли бы легко исправить C implementation of make_struct_type
так, чтобы это ломалось.Последние несколько строк этой функции являются:
sethash(struct_type_hash, name, stype);
if (super) {
mpush(stype, mkloc(su->dvtypes, super));
memcpy(st->stslot, su->stslot, sizeof (val) * su->nstslots);
}
call_stinitfun_chain(st, stype);
return stype;
}
call_stinifun_chain
делает инициализацию, которая заканчивает оценку (new foo)
и хранить его в bar
статическом слоте, а sethash
вызова, что регистрирует тип под своим именем.
Если мы просто отменим порядок, в котором эти функции вызывают, язык и система типов будут по-прежнему совпадать, и почти все будет работать по-прежнему. Тем не менее, спецификатор слота (:static bar (new foo))
не сработает.
Я поместил вызовы в этом порядке, потому что я хотел, чтобы аспекты этого типа были максимально полными, прежде чем подвергать его определяемым пользователем инициализации.
Я не могу думать о какой-либо причине, чтобы foo
не был известен в то время, когда этот тип структуры инициализируется, не говоря уже о серьезной причине. Для статической конструкции для создания экземпляра является законным. Например, мы могли бы использовать его для создания «singleton».
Это похоже на ошибку в Python.
Это происходит потому, что первый случай использования, который вы показываете, происходит до вызова конструктора. –
Почему? Поскольку имя не привязано до тех пор, пока не будет выполнено определение класса. –