0

I am trying to add a default value for parameter d of the FunctionA.evaluate method, but I am getting either a Signature not compatible with previous declaration or 'Function' is not a type name compilation errors. How to do that correctly? The whole project is in my Github.

As I am pretty new with Python and Cython I would also appreciate any other comments regarding the code below (even syntax related).

The goal is to have this simple test pass:

test_ti.py

from ti import SubclassA, SubclassB
import pytest

def test_run_me():

    this_A = SubclassA(a=1, b=2)
    ret_A = this_A.do_that(c=3)  # Throws: TypeError: do_that() takes exactly 2 positional arguments (1 given)
    assert(ret_A == 6)

    this_B = SubclassB(a=1, b=2)
    ret_B = this_B.do_that(c=3, d=4)
    assert(ret_B == 10)

The rest of the project 'skeleton':

superclass.pxd

cdef class Superclass:

    cdef int a
    cdef int b
    cdef int c
    cdef int d

    cdef Function f

    cpdef int do_that(self, int c, int d) except? -1


cdef class Function:

    cpdef int evaluate(self, int a, int b, int c, int d) except *

superclass.pyx

cdef class Superclass:

    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.c = 0


    cpdef int do_that(self, int c, int d) except? -1:
        self.c = c
        self.d = d
        return(self.f.evaluate(self.a, self.b, self.c, self.d))


cdef class Function:

    cpdef int evaluate(self, int a, int b, int c, int d) except *:
        return 0

subclas_a.pyx

cimport superclass
from superclass cimport Superclass, Function


cdef class SubclassA(Superclass):

    def __init__(self, a=0, b=0):
        super(SubclassA, self).__init__(a=a, b=b)
        self.f = FunctionA()


cdef class FunctionA(Function):

    cpdef int evaluate(self, int a, int b, int c, int d) except *:
        # This function needs only 3 parameters, a, b and c and I would
        # love to have a d=0 default value here.
        return(a + b + c)

subclass_b.pyx

cimport superclass
from superclass cimport Superclass, Function


cdef class SubclassB(Superclass):

    def __init__(self, a=0, b=0):
        super(SubclassB, self).__init__(a=a, b=b)
        self.f = FunctionB()


cdef class FunctionB(Function):

    cpdef int evaluate(self, int a, int b, int c, int d) except *:
        return(a + b + c + d)
m-dz
  • 2,342
  • 17
  • 29
  • I suspect that "Function is not a typename" can be fixed by putting function first in the pxd file. The rest I don't 100% understand what you're trying to do - generally subclasses should have the same interface as their base class (so that they can be used in place of a base class) and Cython enforces that strictly because it needs to know at compile time. – DavidW Dec 29 '17 at 21:09
  • 1
    Are you sure this is a Cython issue? If you are new to both Python and Cython, you might try making it work in plain Python first just to clarify your understanding. I don't see any default arguments defined for `do_that` anywhere in your code, so I don't understand why you would expect `do_that(c=3)` to work. – BrenBarn Dec 29 '17 at 21:42
  • @DavidW, the typename error is an issue only when I start fiddling with arguments, so it is not really a problem I guess. Thanks for the last part of your comment, this explains my issue here. – m-dz Dec 30 '17 at 12:59
  • @BrenBarn, yes, I am completely sure. See here: https://stackoverflow.com/a/2398717/4272484, this works perfectly fine in Python, but not in Cython (with `cdef` classes and `cpdef` methods). The part with default arguments for `do_that` is the part I am trying (or rather was, see @DavidW comment) to make to work. Looks like I will need to approach this differently. – m-dz Dec 30 '17 at 13:01
  • @m-dz: That example has no default arguments at all. – BrenBarn Dec 30 '17 at 18:57
  • @BrenBarn, yes, this is an example of the method overloading with different number of parameters, which is actually possible in Cython as well while holding the substitution principle: http://docs.cython.org/en/latest/src/userguide/pyrex_differences.html#optional-arguments-in-cdef-cpdef-functions. The only drawback is I would need a few additional `.pxd` files, but that should be fine. – m-dz Jan 02 '18 at 18:35

0 Answers0