クイックバージョン: Cythonで抽象クラスを宣言する方法は?目標は、インターフェイスのみを宣言することです。これにより、他のクラスがインターフェイスから継承できるようになり、このクラスの実装があってはなりません。
interface.pxd:
cdef class IModel:
cdef void do_smth(self)
impl.pyx:
from interface cimport IModel
cdef class A(IModel):
cdef void do_smth(self):
pass
すべてがうまくコンパイルされますが、Pythonでインポートimpl.so
すると、次のようになります。
ImportError: No module named interface
どうやらメソッドは実際には仮想ではなく、PythonはのIModel
インスタンスを望んでいます
詳細:
私はcython拡張クラス(cdef class Integrator
)を持っており、これは任意のインスタンスで動作し、IModel
インターフェースを実装する必要があります。インターフェイスは、インスタンスにメソッドがあることを確認するだけなvoid get_dx(double[:] x, double[:] dx)
ので、インテグレーターは、モデルを統合するために、すべての統合ステップでインスタンスを呼び出すことができます。アイデアは、cythonでさまざまなモデルを実装し、それらをインタラクティブに統合して、Pythonスクリプトで結果をプロットできるというものです。そのように:
from integrator import Integrator # <-- pre-compiled .so extension
from models import Lorenz # <-- also pre-compiled one, which inherits
# from IModel
mod = Lorenz()
i = Inegrator(mod)
i.integrate() # this one's really fast cuz no python is used inside
# do something with data from i
クラスは次のlorenz.pyx
ようになります。
from imodel cimport IModel
cdef class Lorenz(IModel):
cdef void get_dx(double[:] x, double[:] dx)
# implementation
そしてintegrator.pyx
:
from imodel cimport IModel
cdef class Integrator:
cdef IModel model
def __init__(self, IModel model):
self.model = model
# rest of the implementation
理想的には、IModelはcythonヘッダーファイル(つまりimodel.pxd)のクラス定義の形式でのみ存在する必要がありますが、これまでのところ、醜いダミーの実装クラスをで作成することによってのみ、目的の機能を実現できました。最悪のことは、他のcythonクラスがそれを継承できるように、この役に立たないダミーの実装をコンパイルしてリンクする必要があることです。imodel.pyx
PS:これは抽象クラスの完璧なユースケースだと思いますが、実際に悪いと思われる場合は、親愛なるOOPコーダーの皆さん、他にどのアプローチを使用するか教えてください。