コンストラクタ #
教科書 p.221(Lesson 8.2)オブジェクトを生成する際に,そのオブジェクトの初期化を行うメソッドを コンストラクタ(Constructor) と呼びます.
コンストラクタは,クラスの中で __init__
という名前のメソッドとして定義します.
例えば,Person
オブジェクト作成時に必ず名前と年齢を指定したい場合は,
以下のようにコンストラクタに名前と年齢を受け取るよう引数を定義します.
class Person:
def __init__(self, name, age): # コンストラクタ,名前と年齢を受け取る.
self.name = name
self.age = age
# p = Person() # 引数の数が合わないため,エラーが発生する.
p = Person("John Doe", 30) # Person オブジェクト p を生成するときに名前と年齢を指定する.
print(f"{p.name} is {p.age} years old.") # コンストラクタで指定したので,名前と年齢が出力される.
self.name
と self.age
はそれぞれPerson
オブジェクト(p
)に紐づいた変数です.
name
と age
はコンストラクタの引数で受け取った値を表しています.
以下の図で示すように,self.name
と name
は異なる変数ですが,指し示す値は同じものになります.
コンストラクタを抜けると,name
は参照できなくなりますが,Person
オブジェクトの name
(コンストラクタ内では self.name
)経由で参照できるようになっています.
また,name
,self.name
,p.name
の関係性は以下の図を参照してください.

コンストラクタに,オブジェクトに必要な値を渡して,オブジェクトを初期化するのが一般的です. 近年では,イミュータブル(変更不可)であることが求められることが多いため,コンストラクタで値を初期化し,値を更新しないことが多いです. もし,値の更新が必要な場合は,古いオブジェクトの値を更新せず,新しいオブジェクトを作成するのが一般的です.
例題1. 記念日クラス #
次のように,記念日を表す Aniversary
クラスを定義します.
コンストラクタで,月,日,名前を受け取り,インスタンス変数にそれぞれ代入します.
print
メソッドで,記念日を出力します.
class Aniversary:
def __init__(self, month, day, name):
self.month = month
self.day = day
self.name = name
def print(self):
print(self.str())
def str(self):
return f"{self.month}月{self.day}日は{self.name}です."
h1 = Aniversary(12, 25, "クリスマス")
assert h1.str() == "12月25日はクリスマスです.", "クリスマスの記念日が正しく出力されていません."
h1.print() # 12月25日はクリスマスです.
new_years_day = Aniversary(1, 1, "元日")
assert new_years_day.str() == "1月1日は元日です.", "元日の記念日が正しく出力されていません."
new_years_day.print() # 1月1日は元日です.
例題2. 三角形クラス #
次のように,三角形を表す Triangle
クラスを定義します.
コンストラクタで,3つの辺の長さを受け取り,インスタンス変数にそれぞれ代入します.
class Triangle:
def __init__(self, line1, line2, line3):
self.line1 = line1
self.line2 = line2
self.line3 = line3
def is_valid(self): # 有効な三角形かどうかを判定する.
return self.line1 > 0 and self.line2 > 0 and self.line3 > 0 and \
self.line1 + self.line2 > self.line3 and \
self.line2 + self.line3 > self.line1 and \
self.line3 + self.line1 > self.line2
def area(self):
if not self.is_valid():
return 0
return self.calculate_area_helons_formula()
def calculate_area_helons_formula(self): # ヘロンの公式から面積を求める.
s = (self.line1 + self.line2 + self.line3) / 2
return (s * (s - self.line1) * (s - self.line2) * (s - self.line3)) ** 0.5
t1 = Triangle(3, 4, 5)
assert t1.is_valid(), "有効な三角形であるはずです."
assert t1.area() == 6.0, "面積は 6.0 であるはずです."
t2 = Triangle(1, 1, 3)
assert not t2.is_valid(), "有効な三角形ではないはずです."
assert t2.area() == 0, "面積は 0 であるはずです."
この Triangle
クラスのようにフィールド(変数,ここでは line1
, line2
, line3
)とそれに関連するメソッド(関数.ここでは is_valid
, area
, calculate_area_helons_formula
)をまとめたものを クラス と呼びます.
コンストラクタがないクラス #
クラスの最低限の定義は,以下のようになります.
class TinyClass:
pass
このクラスはコンストラクタが定義されていませんが,TinyClass()
という呼び出しで,TinyClass
のオブジェクトを生成できます.
つまり,引数なしのコンストラクタが暗黙的に定義されていると考えることができます.
そのため,オブジェクトを作成するときに,特に引数を渡す必要がなければ,コンストラクタを定義する必要はありません.