I'm trying to define a Cython class that accepts a function as one of the class attribute in the __init__
function.
I followed this question and tried the following
ctypedef int (*f_type)(int, int)
cdef class ClassWFunction:
cdef f_type f
def __init__( self, f_type f):
self.f = f
def doStuff(self, int x, int y):
return self.f(x, y)
cdef int example_f(int a, int b):
return a*b
classInstance = ClassWFunction(example_f)
classInstance.doStuff(2, 4)
which gives me the error:
Cannot convert 'int (int, int)' to Python object
I also read this page from Cython's documentation and tried following that approach:
cdef class f_type:
cpdef int evaluate(self, int a, int b) except *:
return 0
cdef class ClassWFunctionV2:
cdef f_type f
def __init__( self, f_type f):
self.f = f
def doStuff(self, int a, int b):
return self.f.evaluate(a, b)
cdef class example_f(f_type):
cpdef int evaluate(self, int a, int b) except *:
return a*b
classInstance = ClassWFunctionV2(example_f)
classInstance.doStuff(3, 4)
which gives me a TypeError
:
TypeError: Argument 'f' has incorrect type (expected _cython_magic_9f51dc40b83b28506fce9fb260a84618.f_type, got type)
Hopefully there's a way to make my first attempt work, since this second approach has a lot of boilerplate I don't quite understand! Thanks for your time...
-------- Edit ----------
The point of writing the code this way is twofold:
1) to have a flexible way to change the f
function when instantiating the class.
2) The f
function gets reused in many of the class methods, so I'd like to assign it to self
In my pure python code, I do stuff like
def f1(x): return x**2
def f2(x): return x**3
cl1 = ClassWFunction(f1)
cl2 = ClassWFunction(f2)
and then proceed to do things with those classes. However, I'm not 100% sure this is the best way to go around, so feel free to suggest a different approach.
-------- Edit2 ----------
As a less flexible but (hopefully!) easier alternative, I tried to hard-code the function onto the class. This would fit objective (2) above, even if it doesn't fit objective (1).
Consider (this also gives an error)
ctypedef int (*f_type)(int)
cdef class ClassWFunction:
cdef f_type example_f
cdef double x
def __init__( self, int x):
self.x = x
# Tried with a python function too
cdef int example_f(int z):
return x*z
self.example_f = example_f
def doStuff(self, int x, int y):
return self.example_f(x)*y
classInstance = ClassWFunction(3)
classInstance.doStuff(2, 4)