Cythonバイナリをラップ

前回、Cythonコンパイルしたモジュールについて、インテリセンスが効かないという点が欠点だと挙げた。
nnt339es.hatenablog.com

そこで、このモジュールを再びPythonでラップすることで使いやすさの向上を図ってみた。

ラップ構造

c++ \subset Cython \subsetPython
c++で実装したクラスをCythonでラップすることによってPythonから呼び出せるCコードを変換する。

Cythonを経由するため、コンパイルが楽という利点がある。

バイナリモジュール(Cython)

コンパイルすると[module_name].pydバイナリが生成される。

そのままでも

import module_name

で利用できるが、私の愛用しているPylanceではインテジェンスか効かず、引数や戻り値の型もわからない。

Pythonでラップ

簡単のため、次のようなCythonを用意する。

# cy_person.pyx
# cythonソースの拡張子は.pyx -> .pyd: 実行形式のモジュール
cdef cyPerson:
    cdef str _name
    def __init__(self, str name) -> None:  
        self._name = name
    

    def introduce(self) -> None:
        print(f"I'm {self._name}")

これをラップする。

from cy_person import cyPerson

class Person(cyPerson):
    def __init__(self, name: str) -> None:
        super().__init__(name)


    def introduce(self) -> None:
        super().introduce()

ただ継承して、親のメソッドを呼び出しているだけであるが、実際これが機能する。

パフォーマンス

irisデータセット学習時間(100回統計、層構造[4, 6, 3]、エポック50)

ラップ無し ラップ有り
平均[ms] 30.81 30.94
標準偏差[ms] 2.30 6.15

パフォーマンスは問題なし。

まとめ

Cythonで実装したクラスをPythonで継承して型ヒントを付けてやることで、インテリジェンスの効く使い勝手の良いクラスを利用できる。