我想使用share of declaration for extension types分享一个类的声明,它是cython中另一个类的成员数据。
这是由用户运行的python包装器(run.py
)。它声明了Solver
类。
#! /usr/bin/env python
# filename: run.py
import Solver
S = Solver.Solver()
Result = S.Solve()
Solver
对象有一个cpdef Solve()
成员函数,从代码的python部分调用一次。 Solver
类有cdef object Computation
个成员数据:
# filename: Solver.pyx
from Computation cimport Computation
cdef class Solver:
cdef object Comp
def __cinit__(self):
self.Comp = Computation()
cpdef double Solve(self):
Result = self.Comp.Add(4)
return Result
Computation
类只是一个cython代码:
# filename: Computation.pxd
cdef class Computation:
cdef int a
cdef double Add(self,double b)
和
# filename: Computation.pyx
cdef class Computation:
def __cinit__(self):
self.a = 3
cdef double Add(self,double b):
return self.a + b
setup.py
是:
# filename: setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
package_data = {"Computation": ["Computation.pxd"]},
ext_modules = cythonize(["*.pyx"],include_path=["."]),
)
Solver.Solve()
多次调用Computation.Add()
,但为了简单起见,我在这里抑制了for
循环。关键是调用Add()
应该具有最低成本,因此我已使用cdef
声明它。
所有文件都在同一目录中。我用python setup build_ext --inplace
编译。然后运行./run
我收到以下错误:
Exception AttributeError: "'Computation.Computation' object has no attribute 'Add'" in 'Solver.Solver.Solve' ignored
我有两种解决方法:
Add()
从cdef
更改为cpdef
函数,则不会再出现此错误。但在这种情况下,Solve()
调用的cpdef
与cdef
相比具有开销。我希望避免对cpdef
使用Add()
,因为在实际代码中,Add()
是一个昂贵的代码,并且可能会被调用。如果在Solver
课程中,我没有将Comp
对象声明为成员数据,而只是在Solve()
函数中声明它,我没有得到这个错误。像这样:
# filename: Solver.pyx
from Computation cimport Computation
cdef class Solver:
# No member data here.
cpdef double Solve(self):
# We declare Comp here instead:
Comp = Computation()
Result = Comp.Add(4)
return Result
但我更喜欢Comp
成为Solver
的成员。我的猜测是,通过在python代码Comp
中声明def __cinit__(self)
,cdef
函数不再被声明。
所以,我的问题是,如何共享扩展类型的声明,扩展类型本身是另一个类的成员数据?也就是说,如何在__cinit__()
中声明cython扩展类型?
答案 0 :(得分:0)
自己找到它。只需在Solver.pyx
行
cdef object Comp
应改为
cdef Computation Comp
这里明确地输入了对象。
有了这个,扩展类型的cdef
方法可以在其他地方访问。