2014/02/24

Pythonの staticmethod と classmethod のちがい

Pythonには staticmethod と classmethod というよく似たふたつのデコレータが存在します。一見わかりづらいこれらのちがいについて今回は見ていきます。

結論からざっくり言うと
  • staticmethod の高機能版が classmethod
  • ふたつのちがいは「引数の扱い」
  • staticmethod ではメソッドは実引数をそのまま受け取る
  • classmethod ではクラス自身が暗黙的に第一引数として挿入される
といったちがいになるかと思います。

ことばだけではわかりづらいので、例を見てみましょう。
class MyClass(object):
    @staticmethod
    def static_method(*args):
        print(*args)

    @classmethod
    def class_method(*args):
        print(*args)

MyClass.static_method(1, 3, 5)
# => 1 3 5
# 渡された引数がそのまま順に表示される

MyClass.class_method(1, 3, 5)
# => <class '__main__.MyClass'> 1 3 5
# 渡された引数の前に「クラスそのもの」が表示される
staticmethod でデコレートした方は、引数を print すると実引数がそのまま順番に表示されています。一方で、 classmethod でデコレートした方のメソッドは、実引数のほかにクラスをあらわすオブジェクが順に表示されます。

・・・ということからわかるように、 classmethod では第一引数に暗黙的にクラスそのものが渡される仕組みとなっています。

この classmethod のふるまいは、インスタンスメソッドの場合とまったく同じです。インスタンスメソッドの場合も暗黙的に第一引数にインスタンスが挿入されるので、定義する際は、第一引数を self とするのがきまりとなっています。 classmethod を使う場合もそれと同じように、第一引数を「cls」とすることがルールとなっています(他の名前をつけても文法的なエラーで出ませんが、慣習として・・・)。

@classmethod
    def class_method(cls, args):
        ...

以上です。

ちなみに staticmethod も classmethod もインスタンスから呼び出すこともできます。


参考
decorator - What is the difference between @staticmethod and @classmethod in Python? - Stack Overflow

0 件のコメント: