Cython использует cinit()

#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)