python - Cython 具有不同类型的相同类
问题描述
我有两个 cdef 类B
,C
它们的方法完全相同。它们之间的唯一区别是它们的属性类型:一个有mpz
属性,另一个有int
属性。
我的第一个猜测是使用一个抽象类A
,它会被B
and覆盖C
。问题是 Cython 显然不希望我覆盖属性(另外,我应该为抽象类的属性赋予哪种类型?)。我这样做的错误是:
------------------------------------------------------------
...
cdef class TestModularNumber:
cdef readonly mpz value, modulo
cdef class TestInheritance(TestModularNumber):
cdef readonly int value, modulo ^
------------------------------------------------------------
finite_field/testmodular.pxd:10:22: 'value' redeclared
我的第二个猜测是使用像这样的融合类型的单个类:
ctypedef fused mpz_or_int:
int
mpz
但是 Cython 抱怨我使用这种类型进行操作(例如%
,即使它是为这两种类型定义的)。我得到的错误是:
------------------------------------------------------------
...
ctypedef fused mpz_or_int:
int
mpz
cdef class TestModularNumber:
cdef readonly mpz_or_int value, modulo ^
------------------------------------------------------------
finite_field/testmodular.pxd:12:36: Type is not specialized
------------------------------------------------------------
...
from gmpy2 import invert, powmod
cdef class TestModularNumber:
def __cinit__(self, mpz_or_int value, mpz_or_int modulo):
self.value = value
^
------------------------------------------------------------
finite_field/testmodular.pyx:7:12: Invalid use of fused types, type cannot be specialized
------------------------------------------------------------
...
if not self.has_modular_square_root():
raise ValueError(f"{self.value} is a non-residue modulo {self.modulo}.")
if self.value == 0 or self.value == 1:
return TestModularNumber(self.value, self.modulo)
if self.modulo % 4 == 3:
^
------------------------------------------------------------
finite_field/testmodular.pyx:145:23: Compiler crash in AnalyseExpressionsTransform
现在,我复制/粘贴了这两个类,但这是一个肮脏的 hack,显然,每次我必须修改这些类的方法时,我都会哭:)
我认为要走的路是使用融合类型,但是我怎样才能找到解决这个问题的方法呢?
解决方案
由于Cython 中解释的原因:python 类包装器中的模板通常在 Cython 中不可用。cdef classes
不能有融合的成员。在回答该问题时,我建议使用“复制/粘贴”方法,但可能会尝试将其自动化。
cdef
对于这种特定情况,我想知道您是否可以通过将实现从类中取出到单独的融合函数中来做得更好。首先为您定义一个融合类cdef classes
ctypedef fused cdef_pz_or_int:
# cdef classes _can_ be part of fused types
TestModularNumber
TestInheritance
我建议类之间不要有任何继承关系——只要让它们实现一个(半)通用接口。
实际的实现是在非成员融合函数中:
cdef has_modular_square_root(cdef_pz_or_int self):
value = self.value # cython should be able to infer this type
# more logic goes here....
您显然可以混合和匹配cdef_pz_or_int
以及pz_or_int
作为参数(如果您需要这样做),但是它可能需要为所有组合生成有效代码。
我不是 100% 相信这对你有用 - 如果不是,我很乐意删除它。
推荐阅读
- c# - 查找对象左侧的位置
- google-forms - Google 表单日期字段在 Chrome 上未格式化
- python - 对第二低分数的嵌套列表进行排序
- java - .class - 这个结构是什么以及它是如何工作的?
- amazon-web-services - 将对 beantalk 服务的访问限制为 cloudfront
- laravel - Laravel VueJS axios拦截器访问vue应用
- character-encoding - org.owasp.esapi.reference.DefaultEncoder 与 org.owasp.encoder.Encode
- python - 有没有办法用 python 写入 github 文本文件?
- ios - 哪个是iOS移动应用程序性能测试的最佳工具
- amazon-web-services - 使用 Terraform 部署到多个 AWS 账户?