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 getvaluemethod:

attributeerror: "attributeerror: "'cytest.kernel' object has no attribute 'getvalue'" in 'cytest.model.run' 

what like

  1. access cdef methods of kernel cdef method run, without python overhead.
  2. 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

Popular posts from this blog

android - Gradle sync Error:Configuration with name 'default' not found -

java - Andrioid studio start fail: Fatal error initializing 'null' -

html - jQuery UI Sortable - Remove placeholder after item is dropped -