#cython
#cython
Вопрос:
У меня есть:
cdef class BaseClass():
def __cinit__(self,char* name):
print "BaseClass __cinit__()"
#...
def __dealloc__():
print "BaseClass __dealloc__()"
#...
cdef class DerClass(BaseClass):
def __cinit__(self,char* name,int n):
print "DerClass __cinit__()"
#...
def __dealloc__():
print "DerClass __dealloc__()"
#...
когда я вызываю DerClass в cyhton, случается, что конструктор базового класса вызывается автоматически, то, что он должен напечатать, это:
BaseClass __cinit__()
DerClass __cinit__()
DerClass __dealloc__()
BaseClass __dealloc__()
но это не так, это приводит к сбою тех, которые я называю DerClass(‘Ciao’).
почему это происходит и как я могу избежать вызова cinit базового класса.
Спасибо!
Ответ №1:
Приведенный выше ответ может быть не совсем лучшим решением. Чтение раздела «Методы инициализации: __cinit__() и __init__()» по ссылке выше дает эту информацию:
Если ваш тип расширения имеет базовый тип,
__cinit__()
метод базового типа автоматически вызывается перед вызовом вашего__cinit__()
метода; вы не можете явно вызвать унаследованный__cinit__()
метод.
и
Если вы планируете подклассифицировать свой тип расширения в Python, вам может оказаться полезным указать аргументы
__cinit__()
метода * и **, чтобы он мог принимать и игнорировать дополнительные аргументы.
Поэтому моим решением было бы просто заменить аргументы __cinit()__
in BaseClass
, чтобы переменное количество аргументов могло быть передано любому производному классу:
cdef class BaseClass:
def __cinit__(self, *argv):
print "BaseClass __cinit__()"
#...
def __dealloc__(self):
print "BaseClass __dealloc__()"
#...
cdef class DerClass(BaseClass):
def __cinit__(self,char* name, int n):
print "DerClass __cinit__()"
#...
def __dealloc__(self):
print "DerClass __dealloc__()"
#...
Смотрите Здесь для объяснения *args
переменной в python
Ответ №2:
Что ж, вы правы, что вы должны увидеть метод cinit, вызываемый в вашем родительском классе. Это сказано прямо здесь, в документах.
http://docs.cython.org/src/userguide/special_methods.html
Вот что я пытался использовать:
cdef class BaseClass:
def __cinit__(self,char* name):
print "BaseClass __cinit__()"
#...
def __dealloc__(self):
print "BaseClass __dealloc__()"
#...
cdef class DerClass(BaseClass):
def __cinit__(self,char* name,int n):
print "DerClass __cinit__()"
#...
def __dealloc__(self):
print "DerClass __dealloc__()"
#...
Он скомпилировался, но выдал мне эту ошибку, когда я попытался его запустить:
mike@computer:~/testing$ python runner.py
DerClass __dealloc__()
BaseClass __dealloc__()
Traceback (most recent call last):
File "runner.py", line 4, in <module>
DerClass('Ciao', 1)
File "test.pyx", line 2, in test.BaseClass.__cinit__ (test.c:488)
def __cinit__(self,char* name):
TypeError: __cinit__() takes exactly 1 positional argument (2 given)
mike@computer:~/testing$
Поэтому я изменил BaseClass.cinit, чтобы также принимать параметр «int n», который выполняет DerClass.cinit:
cdef class BaseClass:
def __cinit__(self, char * name, int n):
print "BaseClass __cinit__()"
#...
def __dealloc__(self):
print "BaseClass __dealloc__()"
#...
cdef class DerClass(BaseClass):
def __cinit__(self,char* name,int n):
print "DerClass __cinit__()"
#...
def __dealloc__(self):
print "DerClass __dealloc__()"
#...
И теперь, похоже, он работает нормально:
mike@computer:~/testing$ python runner.py
BaseClass __cinit__()
DerClass __cinit__()
DerClass __dealloc__()
BaseClass __dealloc__()
mike@computer:~/testing$
Вот мой runner.py файл:
from test import *
if __name__ == "__main__":
DerClass('Ciao', 1)