コンストラクタ(イニシャライザ)
Pythonの __init__(self, [, …]) はインスタンス生成時に自動的に呼び出されて実行される初期化メソッドで、コンストラクタまたはイニシャライザとよばれます。
# PYTHON_CONSTRUCTOR
# In[1]
# インスタンス生成と同時に"Hello!"を表示するクラス
class Hello:
def __init__(self):
print("Hello!")
# Helloクラスのインスタンスを生成
my_object = Hello()
# Hello!
__init__() の戻り値は常に None なので、return 構文に None 以外を指定すると TypeError が送出されます。
# In[2]
# クラスを定義
class Return_value:
def __init__(self, value):
return value
# インスタンスを生成
x = Return_value(10)
# TypeError: __init__() should return None, not 'int'
インスタンス生成時に受け取った引数 (インスタンス変数) は __init__() に記述しておきます。
# In[3]
# Squareクラスを定義
class Square:
def __init__(self, x):
# 引数を2乗してオブジェクトの属性値に格納する
self.value = x ** 2
# Squareクラスのインスタンスを生成
my_object = Square(5)
# value属性を表示
print(my_object.value)
# 25
デストラクタ (ファイナライザ)
Pythonの __del__(self) はインスタンスが破棄される(リソースが解放される)ときに呼び出されるメソッドです。コンストラクタと対になるメソッドで、デストラクタまたはファイナライザとよばれます。たとえば、次のようなプロフィール管理クラスを定義したとします。
# PYTHON_DESTRUCTOR
# In[1]
# プロフィール管理クラス
class Profile:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
# デストラクタ
def __del__(self):
print("インスタンスは破棄されました")
Profile クラスのインスタンスを生成して、name 属性を参照してみます。
# In[2]
# Profileクラスのインスタンスを生成
mariko = Profile("刑部真理子", 38, "女性")
# インスタンスのname属性を表示
print(mariko.name)
# 刑部真理子
del 構文を使うと、インスタンスを明示的に破棄できます。
del mariko
# インスタンスは破棄されました
再度、name 属性を参照しようと試みても、すでにインスタンスが消失しているので NameError が送出されます (そのような名前のオブジェクトは存在しないという意味です)。
# In[3]
# インスタンスのname属性を表示
print(mariko.name)
# NameError: name 'mariko' is not defined
del で明示的に宣言しなくてもインスタンスが破棄されることがあります。
もう1つ Profile クラスのインスタンスを作成してみます。
# In[4]
# Profileクラスのインスタンスを生成
suzune = Profile("城戸涼音", 26, "女性")
# インスタンスのname属性を表示
print(suzune.name)
# 城戸涼音
変数 suzune に別のオブジェクトへの参照を割り当てると、元々参照していたオブジェクトは破棄されます。
# In[5]
suzune = 100
# インスタンスは破棄されました
コメント
Google Colabo のコードセルで「デストラクタ」の In[1]~[5] のプログラムを順番に実行していくと、コンストラクタの実行はうまくいくのですが、del mariko や suzune = 100 を実行してもデストラクタが実行されない ( 「インスタンスは破棄されました」が表示されない ) 場合が多々あります。
In[1]~[5] のプログラムを一つにまとめて一つのコードセルで実行すると、下記のようにきちんとデストラクタが実行されます。これで問題ないと考えてよいでしょうか。
“`
刑部真理子
インスタンスは破棄されました
城戸涼音
インスタンスは破棄されました
“`
私も試してみましたが、おっしゃるように、Google Colab ではデストラクタがうまくはたらいていないようです。Jupyter Notebook で同じコードを実行すると、問題なく動作しました(当サイトに掲載されているコードは一部を除いて、Jupyter Notebook で動作確認しています)。Google Colab と Jupyter Notebook で、なぜこのような違いが出るのか、正直今のところ見当もつきません。ただ、In[3] を実行すると NameError が出力されるということは、インスタンスは破棄されている(参照が解放されている)と思われるので、__del__() 内部の print() が何らかの原因で実行されなかったことになります。引き続き調査してみて、何かわかったらお伝えします。少々お時間をください。m(_ _)m