staticmethod が callable になりました
Pythonで定義した関数とCで定義した関数は型が異なり、振る舞いにも幾らかの違いがあります。これがPython実装とC実装の両方を提供する場合に、挙動の一貫性がないという問題になります。
今回問題になったのは、Cで定義した関数は勝手にメソッドにはならないという点です。
>>> def mylen(x): return len(x) ... >>> class C: ... len = len ... mylen = mylen ... >>> C().len([]) 0 >>> C().mylen([]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: mylen() takes 1 positional argument but 2 were given
Python で定義した mylen(x)
をクラス変数に代入してインスタンスの属性として呼び出すと、自動的にメソッド扱いされてCのインスタンスが x
に渡されてしまいます。
インスタンスメソッドやクラスメソッドにしないように @staticmethod
を使うと良さそうですが、Python 3.9まで staticmethod
はただのディスクリプタで、クラスやインスタンス経由で利用しないといけませんでした。
>>> @staticmethod ... def mylen(x): return len(x) ... >>> class C: ... mylen = mylen ... >>> C().mylen([]) 0 >>> mylen([]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'staticmethod' object is not callable
これが先ほどのコミットで変更され、 staticmethod がそのまま呼び出せるようになりました。
Python 3.10.0a7+ (heads/master:553ee2781a, Apr 12 2021, 13:46:28) [Clang 12.0.0 (clang-1200.0.32.29)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> @staticmethod ... def mylen(x): return len(x) ... >>> class C: ... mylen = mylen ... >>> C().mylen([]) 0 >>> mylen([]) 0
Python 3.10a7 はリリース済みなので、この変更が反映されるのは次の Python 3.10b1 からになります。