簡體   English   中英

Cython 具有不同類型的相同類

[英]Cython same classes with different types

我有兩個 cdef 類BC ,它們的方法完全相同 它們之間的唯一區別是它們的屬性類型:一個具有mpz屬性,另一個具有int屬性。

我的第一個猜測是使用抽象的 class A ,它將被BC覆蓋。 問題是 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_intpz_or_int混合並匹配為 arguments (如果您需要這樣做),但是它可能需要為所有組合生成有效代碼。


我不是 100% 相信這對你有用 - 如果不是,我很樂意刪除它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM