从getattr调用Cython扩展类cpdef方法时如何强制执行C版本?
Cython扩展类方法调用的版本选择问题
问题背景
用户定义了如下Cython扩展类:
cdef class A: def __init__(self): getattr(self, 'meth1')() cpdef void meth1(self): print('Calling meth1')
用户的疑问是:这里通过getattr调用的meth1,执行的是Python版本还是C版本?用户自己判断并验证了是Python版本,现在想知道:除了用cpdef包裹cdef函数外,有没有其他方法强制执行C版本?
测试验证代码及输出
用户编写了测试代码来验证方法的绑定形式:
cdef class A: def __init__(self): print("meth1 : ", getattr(self, 'meth1')) print("meth2 : ", self.meth2) cpdef void meth1(self): pass cdef void meth2(self): pass
执行后输出:
meth1 : <bound method A.meth1 of <_cython_magic_....A object at ...>> meth2 : <bound method __Pyx_CFunc_void__lParenA__rParen_to_py_4self.<locals>.wrap of <_cython_magic_....A object at ...>>
可行解决方案
这里提供几种绕过Python版本、直接调用C版本方法的方式:
- 直接静态调用方法:在Cython代码里,不要用
getattr这类Python层面的属性查找,直接写self.meth1()。Cython在编译时会识别这是对C类方法的静态调用,直接生成调用C版本的代码,跳过Python的方法包装流程。 - 显式声明C类类型:在函数内部把
self转换成具体的C类类型,让Cython更精准地解析方法调用。比如修改__init__方法:
def __init__(self): cdef A self_c = self self_c.meth1()
这样self_c.meth1()会直接调用C版本的方法。
- 避免Python属性查找机制:
getattr是Python内置函数,必然走Python的属性查找逻辑,返回的是方法的Python包装器。只要避开这种动态属性获取,用Cython的静态类型调用,就能触发C版本方法的执行。
内容的提问来源于stack exchange,提问作者Ipse Lium
相关产品推荐
相关产品推荐

