[Python] 13. クラス関数(class method)とダック・タイピング、そして特殊メソッド


Study / Python    作成日付 : 2020/06/11 19:42:29   修正日付 : 2020/06/11 19:42:29

こんにちは。明月です。


この投稿はPythonでクラス関数(class method)とダック・タイピング、そして特殊メソッドに関する説明です。


クラス関数(class method)

以前の投稿でPythonクラスと関数に関して説明したことがあります。

link - [Python] 12. クラス(Class)を使う方法

link - [Python] 06. 関数(function) - インライン関数、callbak、ラムダ(lambda)そしてクロージャ


クラスで関数を使う方法は一番のパラメータでselfを入れるとクラスをインスタンス生成した後関数を呼び出せます。

# クラス生成
class TestClass():
  # コンストラクタ
  def __init__(self):
    # 内容は空
    pass
  # 関数
  def call_function(self):
    # コンソール出力
    print("call")
# インスタンスを生成
obj = TestClass()
# 関数を呼び出す。
obj.call_function()


Pythonではクラス関数という関数があります。他のプログラム言語ならstatic関数ということです。

static関数はインスタンスを生成がしなくて呼び出せるものです。

# クラス生成
class TestClass():
  # この変数はstatic変数です。変数の中でアンダーバー(_)が二つあるのでprivateタイプになる。
  __count = 0
  def __init__(self):
    # static変数はインスタンスと関係ないデータなのでselfでアクセスすることではない。
    TestClass.__count = TestClass.__count + 1
  # 関数
  def call_function(self):
    # コンソール出力
    print("call")
  # classmethodデコレーターを使う。そうするとクラス関数、つまりstatic関数になる。
  # パラメータでselfがない
  @classmethod
  def generated_class_count(cls):
    # コンソール出力
    print(cls.__count)
# インスタンスを生成するたびに__countは1ずつ増加する。
obj = TestClass()
obj1 = TestClass()
obj2 = TestClass()
# 呼ばれた個数を出力
TestClass.generated_class_count();



ダック・タイピング

ダック・タイピングはC#のdynamic変数と似ているし、javascriptのコールバック関数と似ています。

# TestClass1クラスの中でcall_function関数がある。
class TestClass1():
  # コンストラクタ
  def __init__(self):
    pass
  # 関数
  def call_function(self):
    # コンソール出力
    print("TestClass1 call");	
 	
# TestClass2クラスの中でcall_function関数がある。
class TestClass2():
  # コンストラクタ
  def __init__(self):
    pass
  # 関数
  def call_function(self):
    # コンソール出力
    print("TestClass2 call")

# TestClass3クラスの中でcall_function関数がある。
class TestClass3():
  # コンストラクタ
  def __init__(self):
    pass
  # 関数
  def call_function(self):
    # コンソール出力
    print("TestClass3 call")

# objのcall_function関数を呼び出す。
def call_function(obj):
  # objのcall_function関数を呼び出す。
  obj.call_function()

# インスタンスを生成
obj1 = TestClass1()
obj2 = TestClass2()
obj3 = TestClass3()

# 各インスタンスをcall_functionを通ってクラスのcall_function関数を呼び出す。
call_function(obj1)
call_function(obj2)
call_function(obj3)


Pythonではインターフェイスが存在しないからダック・タイピングで多態性を実現したようです。でも、インタフェースがない環境でダック・タイピングを作成すると逆にバグの発生や可読性が悪くなると思います。

個人的な考えですが上のソースみたいに作成して、後にTestClass3クラスのcall_functionを変更したり削除したらエラーが発生する可能性があります。個人的な考えです。


特殊メソッド

特別なメソッドは、JavaやC#なら最上位クラスObjectで宣言された基本関数の意味です。つまり、ToString()と同様のことでしょう。

link - https://docs.python.org/3/reference/datamodel.html#special-method-names


特殊メソッドは種類がすごく多いですが、よく使う__eq__と__ne__、__str__、__repr__、__len__を説明します。

# クラス生成
class TestClass():
  # コンストラクタ
  def __init__(self, data):
    # メンバー変数設定
    self.data = data
  # __eq__関数
  def __eq__(self, obj):
    # コンソール出力
    print("__eq__ call")
    # 結果(メンバー変数比較)
    return self.data == obj.data
  # __ne__関数
  def __ne__(self, obj):
    # コンソール出力
    print("__ne__ call")
    # 結果(メンバー変数比較)
    return self.data != obj.data
  # __str__関数
  def __str__(self):
    # コンソール出力
    print("__str__ call")
    # 結果(メンバー変数出力)
    return str(self.data)
  # __len__
  def __len__(self): 
    # コンソール出力
    print("__len__ call")
    # 結果(メンバー変数長さ)
    return len(self.data)
# インスタンスを生成
obj1 = TestClass("a")
obj2 = TestClass("b")

# __eq__が呼び出す。
print(obj1 == obj2)
# __ne__が呼び出す。
print(obj1 != obj2)
# __str__が呼び出す。
print(obj1)
# __len__が呼び出す。
print(len(obj1))


特殊メソッドは演算子を再定義する機能があります。よく使うとソースステップをたくさん減らせると思います。


ここまでPythonでクラス関数(class method)とダック・タイピング、そして特殊メソッドに関する説明でした。


ご不明なところや間違いところがあればコメントしてください。

最新投稿