![](/img/trans.png)
[英]Understanding the benefit of using Cython Extension types vs Python Classes
[英]Cython same classes with different types
我有兩個 cdef 類B
和C
,它們的方法完全相同。 它們之間的唯一區別是它們的屬性類型:一個具有mpz
屬性,另一個具有int
屬性。
我的第一個猜測是使用抽象的 class A
,它將被B
和C
覆蓋。 問題是 Cython 顯然不希望我覆蓋屬性(另外,我應該為抽象 class 的屬性賦予哪種類型?)。 我這樣做的錯誤是:
------------------------------------------------------------
...
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
我的第二個猜測是使用單個 class 與這樣的融合類型:
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
現在,我復制/粘貼了這兩個類,但這是一個骯臟的技巧,顯然,每次我必須修改這些類的方法時,我都會哭:)
我認為 go 的方法是使用融合類型,但我怎樣才能找到解決這個問題的方法?
由於 Cython 中解釋的原因:python class 包裝器中的模板通常在 Cython 中不可用。 cdef classes
不能有融合成員。 在回答該問題時,我建議使用“復制/粘貼”方法,但可能會嘗試將其自動化。
對於這種特定情況,我想知道您是否可以通過將實現從 class 中取出到單獨的cdef
融合函數中來做得更好。 首先為您的cdef classes
定義一個融合的 class
ctypedef fused cdef_pz_or_int:
# cdef classes _can_ be part of fused types
TestModularNumber
TestInheritance
我建議在類之間不要有任何 inheritance 關系——只要讓它們實現一個(半)公共接口。
實際的實現是在非成員融合函數中:
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
混合並匹配為 arguments (如果您需要這樣做),但是它可能需要為所有組合生成有效代碼。
我不是 100% 相信這對你有用 - 如果不是,我很樂意刪除它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.