是否可以实现支持in-place操作的Cython函数?
结论
你给出的示例代码不能实现预期的in-place修改效果,原因如下:
- Python中的int是不可变类型,你在
def mysub(int a, int b)中定义的参数a、b是Cython自动转换生成的局部C int变量,你对这两个变量取地址传入C函数,修改的仅为函数栈上的局部变量值,不会对Python外层作用域中传入的原始int对象产生任何影响,调用结束后外层的a、b值不会发生变化。
可行的实现方案
方案1:返回修改后的值(最符合Python开发习惯)
直接将修改后的结果以元组形式返回,调用时重新赋值即可:
cdef extern void mysub_wrapper(int *a, int *b) def mysub(int a, int b): mysub_wrapper(&a, &b) return a, b
调用方式:
a = 1 b = 0 a, b = mysub(a, b) # 此时b的值为2
方案2:使用可变对象包裹整数
利用列表、numpy数组等可变对象存储整数,修改容器内的元素实现in-place效果:
用列表实现示例:
cdef extern void mysub_wrapper(int *a, int *b) def mysub(list a, list b): # 要求入参为仅包含1个整数的列表 cdef int ca = a[0] cdef int cb = b[0] mysub_wrapper(&ca, &cb) a[0] = ca b[0] = cb
调用方式:
a = [1] b = [0] mysub(a, b) # 此时b[0]的值为2
用numpy数组实现示例(效率更高):
import numpy as np cimport numpy as np cdef extern void mysub_wrapper(int *a, int *b) def mysub(np.ndarray[np.int32_t, ndim=0] a, np.ndarray[np.int32_t, ndim=0] b): mysub_wrapper(<int*>a.data, <int*>b.data)
调用方式:
a = np.array(1, dtype=np.int32) b = np.array(0, dtype=np.int32) mysub(a, b) # 此时b的值为2
内容的提问来源于stack exchange,提问作者nicholaswogan
相关产品推荐
相关产品推荐

