我正在尝试为 Cython 文件中的
cdef class
定义一些内置算术运算。
起初我尝试像这样制作
__pow__
函数:
def __pow__(self, other, modulo=None):
pass
但是编译时收到如下错误信息:
该参数不能有默认值
(错误消息引用的参数是
modulo
)
删除
modulo
的默认值允许文件正确编译,但强制用户提供第三个参数,这不仅奇怪且烦人,而且还阻止使用 **
运算符 (pow
必须使用)。
如何在 Cython 中实现
__pow__
以使第三个参数是可选的?
您不需要为
__pow__
中的第三个参数分配默认值:cython 会为您完成此操作。当仅使用 2 个参数的 **
运算符或 pow()
时,第三个参数设置为 None
。如果您不打算处理 3 参数形式的 None
,则可以显式检查 return NotImplemented
和 pow
。
一个简单的 cython 类示例,位于 _cclass_test.pyx 中:
# cython: language_level=3
cdef class Test:
def __pow__(x, y, z):
if z is None:
print("Called with just x and y")
else:
print("Called with x, y and z")
及其使用示例:
import pyximport
pyximport.install()
from _cclass_test import Test
t = Test()
t ** 5
pow(t, 5)
pow(t, 5, 3)
输出:
$ python cclass_test.py
Called with just x and y
Called with just x and y
Called with x, y and z
(使用 Cython 版本 0.29.12 进行测试)
您可以使用装饰器来欺骗 cython 编译器,使其认为该参数没有默认值:
def trickster(func):
def wrapper(self, other, modulo=None):
return func(self, other, modulo)
return wrapper
class MyClass:
...
@trickster
def __pow__(self, other, modulo):
...
在较新版本的 Cython 中,您的代码将按原样接受。
参见 [BUG]
__pow__
所需的参数数量阻止编译和解释纯 python 代码兼容性 · 问题 #5160 · cython/cython
当然,如果最后一个参数的默认值不是
None
,Cython 仍然会抱怨。理应如此。
(如果您确实想要非
None
默认参数,您可以检查None
并进行相应替换)