Ответ 1
Проблема в том, что Cython не знает тип данных вашей переменной py_context
во время компиляции. Вызов функций cdef
разрешается во время компиляции, и нет механизма для его определения во время выполнения путем поиска атрибута (как и с обычными функциями Python).
[Обратите внимание, что функции def
, написанные в Cython, все еще скомпилированы и могут указывать типы данных, поэтому они вполне способны вызывать функции cdef
, если у них есть правильная информация.]
Вы не укажете соответствующий код, где это происходит неправильно (конструктор типа B
), но здесь очень упрощенный пример, который, надеюсь, даст вам пару способов исправить его:
cdef class A:
cdef f(self):
return
def f1(var):
var.f()
#f1(A()) # will fail at runtime with an attribute error
В f1
тип var
неизвестен, и поэтому вы не можете вызывать функции cdef
.
def f2(A var):
var.f()
f2(A()) # will work
f2(1) # will fail, int can't be converted to A
В f2
тип var
ограничен A
, и поэтому он может с радостью вызвать функции cdef
, связанные с A
. Если вы передадите то, что не соответствует A
, вы получите TypeError
во время выполнения.
def f3(var):
cdef A another_reference_to_var = var # this does test that the types match
another_reference_to_var.f()
f3(A()) # will work
f3(1) # will fail, int can't be converted to A
Функция f3
может принимать переменную любого типа. Однако, когда вы назначаете его another_reference_to_var
, который cdef
ed должен быть A
, он проверяет, соответствует ли тип (и вызывает исключение во время выполнения, если это не так). Поскольку another_reference_to_var
, как известно, A
во время компиляции, вы можете вызвать функции A
cdef
.
По существу, вам нужно указать тип соответствующего ввода для вашей функции __cinit__
.