[Python] classメソッドとstaticメソッド

2018年4月9日月曜日

python

classメソッドとstaticメソッド

Pythonにはclassメソッドとstaticメソッドがあるけど、Javaなんかに慣れたプログラマーからすると、最初はわかりづらい。

具体的にはこんな感じ。

class.py
#!/usr/bin/python
class BaseClass:
  @classmethod
  def class_method(cls):
    print("class_method: {0}".format(cls))

  @staticmethod
  def static_method():
    print("static_method: {0}".format(BaseClass))

class SubClass(BaseClass):
  pass

BaseClass.class_method()
BaseClass.static_method()
SubClass.class_method()
SubClass.static_method()
$ ./class.py
class_method: __main__.BaseClass
static_method: __main__.BaseClass
class_method: __main__.SubClass
static_method: __main__.BaseClass

classメソッド

第一引数でクラスが渡される時点でなんとなくわかるけど、classメソッドは実行時のクラスで実行される。
このため、BaseClassで呼ばれれば、BaseClassのメソッド、SubClassで呼ばれれば、SubClassのメソッドとして実行される。

staticメソッド

一方、staticメソッドは実行時のクラスを知る手立てがない(少なくとも僕は知らない)。
なので、先ほどのサンプルプログラムではBaseClassを陽に記述している。
この場合はSubClassで呼ばれても、BaseClassのメソッドとして実行される。というより、そもそもどこかのクラスに結びついているという印象が希薄。

インスタンスメソッドから呼び出す。

ちなみに以下のようにすれば、インスタンスメソッドから実行時のクラスで呼び出すこともできる。

class2.py
#!/usr/bin/python
class BaseClass:
  def instance_method(self):
    print("instance_method: {0}".format(self.__class__))
    self.class_method()
    self.static_method()

  @classmethod
  def class_method(cls):
    print("class_method: {0}".format(cls))

  @staticmethod
  def static_method():
    print("static_method: {0}".format(BaseClass))

class SubClass(BaseClass):
  pass

b = BaseClass()
b.instance_method()
b = SubClass()
b.instance_method()
$ ./class2.py
instance_method: __main__.BaseClass
class_method: __main__.BaseClass
static_method: __main__.BaseClass
instance_method: __main__.SubClass
class_method: __main__.SubClass
static_method: __main__.BaseClass

使い分け?

classメソッドは、クラスには関係付けたいけど、個々のインスタンスには関係付けない。継承関係で実行時のクラスは表現したい。
staticメソッドは、あるクラスと密接な関係があるけど、派生クラスとは関係付けたくない。個々のインスタンスとも関係ない。

...って、とこなのかな。