【发布时间】:2020-04-11 22:44:01
【问题描述】:
我有两个 cdef 类 B 和 C,它们的方法完全相同相同。它们之间的唯一区别是它们的属性类型:一个有mpz 属性,另一个有int 属性。
我的第一个猜测是使用抽象类A,它会被B 和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,显然,每次我必须修改这些类的方法时,我都哭了 :)
我认为要走的路是使用融合类型,但我怎样才能找到解决这个问题的方法呢?
【问题讨论】:
-
这是一个非常相似的问题stackoverflow.com/questions/31436593/…。不幸的是,我认为没有出现任何新的解决方案。基本上你可能确实需要复制和粘贴,但你可以尝试自动化
-
该死的,希望有一个更漂亮的解决方案:'(不过还是谢谢!
-
肯定会很好。我确实有另一个想法可能适用于您的具体情况......
-
真的吗?解决方法是什么,或者至少是原则,所以我也可以考虑一下?
-
我已通过建议发布作为答案。它非常模糊且不完整,但我认为它应该可以帮助您避免一些代码重复。如果它不起作用,那么告诉我,我会摆脱它(以免误导其他人)