Reputation: 1122
I coded these four classes in jupyter-notebook. first two classes are in python and the other two classes with similar operations are in cython:
%load_ext cython
%%cython
# py_child inherits from py_parent
class py_parent:
def __init__(self, var1, var2):
self.var1 = var1
self.var2 = var2
def func1(self):
return self.var1 + self.var2
def func2(self):
return self.var1 * self.var2
class py_child(py_parent):
def func1(self, inp):
return self.var1 + self.var2, self.var1 + inp, self.var2 + inp
# In the next cell I coded these modules
# cy_child inherits from cy_parent
cdef class cy_parent:
cdef public:
int var1, var2
def __init__(self, var1, var2):
self.var1 = var1
self.var2 = var2
cpdef int func1(self):
return self.var1 + self.var2
cpdef int func2(self):
return self.var1 * self.var2
cdef class cy_child(cy_parent):
def __init__(self, var1, var2):
super().__init__(var1, var2)
cpdef tuple func1(self, int inp):
return self.var1 + self.var2, self.var1 + inp, self.var2 + inp
I run code below for python classes and it works just fine:
a = py_child(1,1)
print(a.func1(2))
But for cy_child and cy_parent I get this error:
cpdef tuple func1(self, int inp):
^
------------------------------------------------------------
Signature not compatible with previous declaration
I also get this error after that:
Call with wrong number of arguments (expected 1, got 2)
Why this error happens for cython classes but not python classes.
Assume that I want the superclass cy_parent
keep the func1
function unchanged and want to modify its subclass cy_child.func1
function in the way I showed. How can I fix the error then?
Any suggestion would be highly appreciated.
Upvotes: 1
Views: 819
Reputation: 30917
This will "work" if you change cpdef
to def
, but what you're doing makes no sense.
Inheritance usually indicates a "is a" relationship - i.e. cy_child
is a cy_parent
and should be able to do everything a cy_parent
can do, (and possibly some other stuff). Therefore, it can be used in your code anywhere that you can use a cy_parent
. By trying to change the function signature you're making it so that it can do longer do the same things and so breaking that rule.
With a cpdef
function your asking Cython to generate code so that the following code generates a fast C function call to the correct function whether it's passed a cy_parent
or cy_child
:
def example(cy_parent x):
x.func1()
Since the functions take different numbers of arguments it is not possible to do this and hence Cython (rightly) complains. With pure Python code you put the problem off until you run the code, but the problem still exists (you'll get an exception about the wrong number of arguments).
There's two "solutions":
cy_child
then you should give the new function a different name (since it's doing something different). This represents a case where you still want to be able to use cy_parent
's func1
with cy_child
but you also want the option of doing a similar action with an extra argument.Upvotes: 1