Python3で@staticmethod付けなくてもクラスのmethodを直接呼べて驚いた話
通常classのmethodをコールするには、オブジェクトを生成してコールする。
もしくは、@classmethod、@staticmethodを付けて直接コールするのどれかかと思います。
でも、タイトル通り直接呼べました。
環境
Python 3.8.2
@staticmethodつけないでコールする
簡単なサンプルを用意してみましょう。
下記コードでは、@staticmethodを付けていませんがfoo()メソッドが直接呼べちゃいます。
>>> class A:
... def foo(): # @staticmethodつけない
... print('Hello foo')
...
>>> A.foo()
Hello foo <=== なぜか直接呼べる
>>> A().foo()
Traceback (most recent call last): <=== オブジェクトからは呼べない
File "<stdin>", line 1, in <module>
TypeError: foo() takes 0 positional arguments but 1 was given
>>>
@staticmethodつけてコールする
では、今度はつけてみましょう。
@staticmethodを付けてるので直接呼べるのはもちろんですが、オブジェクトからも呼べちゃいます。
>>> class B:
... @staticmethod # @staticmethodつける
... def foo():
... print('Hello foo')
...
>>> B.foo()
Hello foo
>>> B().foo()
Hello foo <=== オブジェクトからも呼べる
>>>
@staticmethodつける、つけないの違い
上記見てもらった通り、オブジェクトからも呼び出せるかどうかしかないように思えるのだけど、ちょっと分からないです。
つい最近まで、python3がこんな仕様だなんて知らなかった。
でも、@staticmethod付けた方が分かりやすいから、自分はこれからも付けます。
参考までに
では、Python2 ではどうだったか確認
環境
Python 2.7.16
確認
>>> class A:
... def foo(): # @staticmethodつけない
... print('Hello foo')
...
>>> A.foo()
Traceback (most recent call last): <=== 直接呼出しはダメ
File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with A instance as first argument (got nothing instead)
>>> A().foo()
Traceback (most recent call last): <=== オブジェクトからも、もちろんダメ
File "<stdin>", line 1, in <module>
TypeError: foo() takes no arguments (1 given)
>>>
>>>
>>> class B:
... @staticmethod # @staticmethodつける
... def foo():
... print('Hello foo')
...
>>> B.foo()
Hello foo <=== @staticmethod つければ呼び出せる
>>> B().foo()
Hello foo
>>>
これを見るとPython2ではやっぱりダメですね。
でも、なんでPython3からOKになったんだろう?気になる。
参考にしたURL
https://stackoverflow.com/questions/43587044/do-we-really-need-staticmethod-decorator-in-python-to-declare-static-method
https://stackoverflow.com/questions/136097/difference-between-staticmethod-and-classmethod