私は Cython を使い始めたばかりで、Cython 固有のものをグーグルで検索するのも非常に難しいことがわかりました。
Cython で Python 関数を再実装しています。Python では次のようになります。
def func(s, numbers=None):
if numbers:
some_dict = numbers
else:
some_dict = default
return sum(some_dict[c] for c in s)
Python 2 と 3 では問題なく動作します。しかし、 and と入力しようとするs
とc
、少なくとも 1 つの Python バージョンで機能しなくなります。私は試した:
def func(char *s, numbers=None):
if numbers:
some_dict = numbers
else:
some_dict = default
cdef char c
cdef double m = 0.0
for c in s:
m += some_dict[<bytes>c]
return m
正直なところ、これは私がまったく機能するようになった唯一のことであり、Python 2 ではまともなスピードアップが得られますが、Python 3 では機能しません。
def func(unicode s, numbers=None):
if numbers:
some_dict = numbers
else:
some_dict = default
cdef double m = 0.0
for c in s:
m += some_dict[c]
return m
しかし、実際には a が発生し、まだ a のKeyError
ように見えます (欠落しているキーはa で始まる場合) ですが、私が言うと.c
char
80
s
'P'
print(type(c))
<class 'str'>
元の型指定されていないコードは両方のバージョンで動作しますが、Python 2 で動作する型付きバージョンよりも約 2 倍遅くなります。
では、Python 3 でまったく動作させるにはどうすればよいでしょうか。また、両方の Python バージョンで同時に動作させるにはどうすればよいでしょうか。型/バージョン チェックで型宣言をラップできますか? それとも、2 つの関数を作成し、そのうちの 1 つを条件付きで公開されている名前に割り当てる必要がありますか?
PS 重要な場合は、文字列に ASCII 文字のみを許可しても問題ありませんが、Cython は明示的なエンコード/デコードを好むように見えるため、そうであるとは思えません。
編集:明示的なエンコードとバイト文字列の反復も試みましたが、これは理にかなっていますが、次のコード:
def func(s, numbers=None):
if numbers:
some_dict = numbers
else:
some_dict = default
cdef double m = 0.0
cdef bytes bs = s.encode('ascii')
cdef char c
for c in bs:
m += some_dict[(<bytes>c).decode('ascii')]
return m
Python 2 での最初の試行よりも 3 倍遅く (純粋な Python 関数の速度に近い)、Python 3 ではほぼ 2 倍遅くなります。