staticmethodによる静的メソッド

入門Python3 6.10


staticmethodデコレータを使うと、クラスに静的メソッドを作ることができます。

class Foo():
    @staticmethod
    def hello():
        return "hello foo"

print(Foo.hello())
$ py main.py
hello foo


と、ここまで書いてみて、あれこれそういやstaticmethod付けなくても動作したような、と思いやってみると

class Foo():
    # staticmethodをつけない
    def hello():
        return "hello foo"

print(Foo.hello())
$ py main.py
hello foo

うん、ちゃんと動く。

ではstaticmethodを付けるのと付けないのとで何が違うのか?

色々調べてみたんですが、どうやら恐らくPython2の時はstaticmethodをつけない場合例外になってたみたいです。

class Foo():
    # staticmethodをつけない
    def hello():
        return "hello foo"

print(Foo.hello()) # Python2だとここで例外がでるっぽい

つまりPython3(正しくはPython3.3以降?)では付けても付けなくても同じってことになるんですかね。

Python3.6をベースに勉強しているのでググって調べると2の時の話とかが混ざってて調べるのが難しいですね・・・。まずは2から勉強した方が良かったのかしら。


追記

もうひとつ違いがありました。それはオブジェクトからメソッドを呼び出す場合の挙動の違いです。

staticmethodを使わない場合例外になります。

class Foo():
    def hello():
        return "hello foo"

foo = Foo()
print(foo.hello())
$ py main.py
Traceback (most recent call last):
  File "main.py", line 8, in <module>
    print(foo.hello())
TypeError: hello() takes 0 positional arguments but 1 was given

オブジェクトからの呼び出しの場合、helloはオブジェクトメソッドとして呼び出されるため、引数にselfが指定されていないので例外となるわけです。


staticmethodを使えばオブジェクトからの呼び出しの場合でもオブジェクトメソッドとしてではなく静的メソッドとして呼ばれることになります。

class Foo():
    @staticmethod
    def hello():
        return "hello foo"

foo = Foo()
print(foo.hello())
$ py main.py
hello foo

このことから基本的には静的メソッドとして提供する場合はstaticmethodにしておいた方が無難と言えるでしょう。