0
1

【Python】クラスのイニシャライザとメソッドで同名の関数を定義するとどうなるか

Last updated at Posted at 2024-07-30

概要

  • 題意の疑問は、pythonインタプリタの挙動を知ることで理解できます

結論

  • それぞれ別の空間(クラスオブジェクトインスタンスオブジェクト)に定義、保持される
    • クラス定義内で記述したメソッドはクラスオブジェクト内のクラス変数として定義される
    • イニシャライザで定義したメソッドはインスタンスオブジェクト内のオブジェクト変数として定義される
  • 呼び出し時は、インスタンスオブジェクトに定義されたメソッドが優先的に呼ばれ、インスタンスにて定義されていない場合にクラスオブジェクト側のメソッドが呼び出される

説明

  • pythonでは、クラスオブジェクトインスタンスオブジェクトは別個のメモリ空間で定義されます
  • メソッド定義とイニシャライザは、それぞれ独立したタイミングで処理されます
  • 具体的には、pythonインタプリタは以下のように処理します
    • クラスオブジェクトについて
      1. クラス定義からクラスオブジェクトを生成
      2. メソッド定義から関数オブジェクトを生成
        3. メソッド定義から関数オブジェクトクラスオブジェクトの変数に代入
    • インスタンスオブジェクトについて
      1. インスタンスオブジェクト生成
        2. インタプリタが__init__メソッドを実行
        3.(__init__関数内でメソッドの代入が記述されていれば)インスタンスオブジェクトの変数に引数で渡された関数オブジェクトを代入
    • メソッド呼び出し時
      1. インスタンス変数からメソッドを探索、実行
      2. 1で見つからなかった場合、クラス変数から探索、実行

テスト環境

  • Python 3.10.12
  • Ubuntu 22.04.4 LTS (WSL2)

テストコード

  • クラス定義
class TestClass():
  def __init__(self, arg_func=None):
    if arg_func is not None:
      self.method = arg_func

  def __call__(self):
    self.method()

  def method(self):
    print("original method called")

def arg_func():
    print("arg func called")

def new_method(self):
    print("new method called")
  • 素のインスタンスと、イニシャライザに関数を渡したインスタンスのテスト
instance = TestClass(); instance()
instance = TestClass(arg_func); instance()
実行結果
original method called
arg func called
  • クラスオブジェクト側のメソッドを上書きした場合
TestClass.method = new_method
instance = TestClass(); instance()
instance = TestClass(arg_func); instance()
実行結果
new method called
arg func called

謝辞

  • コメントの @shiracamus 様、ありがとうございました
0
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1