特殊メソッド

特殊メソッド

特殊メソッド

 Python では基本的にオブジェクトに対する操作は関数 func(object) あるいはメソッド object.func() によって実行されます。

 しかし、すべての操作がこの形で実行されるわけではありません。
 たとえば、オブジェクト同士の加算は算術演算子「 + 」、リストのインデクス 1 から 3 までのスライスは list[1:3] で実行されます。

 このような特殊構文を使うことによって、コードをなるべく簡潔に記述できるように設計されています (足し算を行なうたびに逐一メソッドを記述しなければならないような言語を使いたいとは思わないはずです)。

 とはいえ、構文は特殊であっても、内部的にはあくまでそれぞれのクラスのメソッドとして定義されています。特殊構文で実行できるメソッドは特殊メソッドとよばれ、二重アンダースコアで囲まれています。たとえば、算術演算子「 + 」の機能は __add__() という名前で定義されます。

コンストラクタ (イニシャライザ)

 __init__(self, [, ...]) はインスタンス生成時に自動的に呼び出されて実行される初期化メソッドで、コンストラクタ またはイニシャライザとよばれます。

# CONSTRUCTOR-1

# インスタンス生成と同時に"Hello!"を表示するクラス
class Hello:
     def __init__(self):
        print("Hello!")

# Helloクラスのインスタンスを生成
my_object = Hello()
Hello!

 __init__() の戻り値は常に None なので、return 構文に None 以外を指定すると TypeError が送出されます。

# CONSTRUCTOR-2

# クラスを定義
class Return_value:
    def __init__(self, value):
        return value

# インスタンスを生成
x = Return_value(10)
TypeError: __init__() should return None, not 'int'

 インスタンス生成時に受け取った引数 (インスタンス変数) は __init__() に記述しておきます。

# CONSTRUCTOR-3

# Squareクラスを定義
class Square:
    def __init__(self, x):
        
        # 引数を2乗してオブジェクトの属性値に格納する
        self.value = x ** 2

# Squareクラスのインスタンスを生成
my_object = Square(5)

# value属性を表示
print(my_object.value)
25

 

デストラクタ (ファイナライザ)

 __del__(self) はインスタンスが破棄される (リソースを解法する) ときに呼び出されるメソッドです。コンストラクタと対になるメソッドで、デストラクタ またはファイナライザとよばれます。たとえば、次のようなプロフィール管理クラスを定義したとします。

# DESTRUCTOR-1

# プロフィール管理クラス
class Profile:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex
    
    # デストラクタ
    def __del__(self):
        print("インスタンスは破棄されました")

 Profile クラスのインスタンスを生成して、name 属性を参照してみます。

# DESTRUCTOR-2

# Profileクラスのインスタンスを生成
mariko = Profile("刑部真理子", 38, "女性")

# インスタンスのname属性を表示
print(mariko.name)
刑部真理子

 del 構文を使うと、インスタンスを明示的に破棄できます。

del mariko
インスタンスは破棄されました

 再度、name 属性を参照しようと試みても、すでにインスタンスが消失しているので NameError が送出されます (そのような名前のオブジェクトは存在しないという意味です)。

# DESTRUCTOR-3

# インスタンスのname属性を表示
print(mariko.name)
NameError: name 'mariko' is not defined

 del で明示的に宣言しなくてもインスタンスが破棄されることがあります。
 もう1つ Profile クラスのインスタンスを作成してみます。

# DESTRUCTOR-4

# Profileクラスのインスタンスを生成
suzune = Profile("城戸涼音", 26, "女性")

# インスタンスのname属性を表示
print(suzune.name)
城戸涼音

 変数 suzune に別のオブジェクトへの参照を割り当てると、元々参照していたオブジェクトは破棄されます。

# DESTRUCTOR-5

suzune = 100
インスタンスは破棄されました