python - Cython: have sequence of Extension Types as attribute of another Extension Type with access to cdef methods -
suppose defined following cython class
cdef class kernel: cdef readonly double def __init__(self, double a): self.a = cdef public double getvalue(self, double t): return self.a*t
now i'd define extension type has sequence of kernels attribute. like:
cdef class model: cdef readonly kernel[:] kernels cdef unsigned int n_kernels def __init__(self, kernel[:] ker): self.kernels = ker self.n_kernels = ker.shape[0] cdef double run(self, double t): cdef int cdef double out=0.0 in range(self.n_kernels): out += self.kernels[i].getvalue(t) return out
however, doesn't work. first need substitute kernel[:]
with object[:]
, otherwise following error gcc
‘pyobject’ has no member named ‘__pyx_vtab’
if use object[:]
compiles fine error when attempting access getvalue
method:
attributeerror: "attributeerror: "'cytest.kernel' object has no attribute 'getvalue'" in 'cytest.model.run'
what like
- access
cdef
methods ofkernel
cdef
methodrun
, without python overhead. - type-check elements of kernels.
my current workaround
at moment use following solution doesn't satisfy requirements above:
cdef class kernel: cdef readonly double def __init__(self, double a): self.a = cpdef public double getvalue(self, double t): return self.a*t cdef class model: cdef readonly object[:] kernels cdef unsigned int n_kernels def __init__(self, object[:] ker): self.kernels = ker self.n_kernels = ker.shape[0] def run(self, double t): cdef int cdef double out=0.0 in range(self.n_kernels): out += self.kernels[i].getvalue(t) return out
i.e. declare methods of kernel class cpdef
can accessed python , use object[:]
.
question
is there way achieve points 1 , 2 above in cython without python overhead?
thanks in advance time.
nb: don't know length of sequence in advance.
edit
following @davidw advice modified code follows
# module cytest import cython cdef class kernel: cdef readonly double def __init__(self, double ): self.a = cdef public double getvalue(self, double t): return self.a*t cdef class model: cdef readonly kernel[:] kernels ### added attribute cdef kernel k cdef unsigned int n_kernels def __cinit__(self, kernel[:] ker): self.kernels = ker self.n_kernels = ker.shape[0] cpdef double run(self, double t): cdef int cdef double out=0.0 in range(self.n_kernels): # assign new attribute each time # , access cdef method self.k = self.kernels[i] out += self.k.getvalue(t) return out
now compiles , runs fine (and faster previous workaround), if still have python overhead when accessing kernel[:]
attribute.
i put here example of building , calling model
import cytest import numpy np ker_list = [cytest.kernel(i*1.0) in range(3)] # transform numpy array # able pass 'model' constructor ker_arr = np.array(ker_list) # create model instance model = cytest.model(ker_arr) # call method run print model.run(1.0)
Comments
Post a Comment