変数と関数をひとまとめにしたものをクラスと呼ぶ。使用者側から見たクラスは、変数と関数がまとめられた All-in-One ツールボックのようなもので、箱内部の処理を気にすることなく、使いたい機能だけ選んで使えることができる。開発者側から見たクラスは、設計書そのものであり、変装や関数の機能が細分化されて定義され、抽象度の高く(応用範囲の広く)、再利用しやすくなるものとなっている。
ポケモンカードのクラス(設計書)を作成する例を示す。まず、1 つのポケモンカードを眺めたとき、そのカードには、ポケモンの名前、HP、タイプなどの属性がある。また、動作として攻撃と逃げるがある。これらの属性と動作(関数)を、クラスとして設計すると右のようになる。
class Pikachu:
def __init__(self):
self.name = 'pikachu'
self.hp = 70
self.type = 'electric'
def attack(self, attack_type):
if attack_type == 'quick_attack':
x = 10
else:
x = 60
return x
def escape(self):
return 0
ピカチューのポケモンカードは様々な種類のものがある。例えば、HP だけが異なっているものも存在する。このようなカードのクラス(設計書)は、上の設計書のうち self.hp
の部分を修正することによって、簡単に作れる。
class Pikachu:
def __init__(self):
self.name = 'pikachu'
self.hp = 90
self.type = 'electric'
def attack(self, attack_type):
if attack_type == 'quick_attack':
x = 10
else:
x = 60
return x
def escape(self):
return 0
ピカチュウの HP が変わる度に、クラスを書き換えるのが大変である。そこで、予め変わることが予想される属性について、変数として扱うと、1 つのクラス(設計書)で様々なカードを作成できる。
class Pikachu:
def __init__(self, hp=70):
self.name = 'pikachu'
self.hp = hp
self.type = 'electric'
def attack(self, attack_type):
if attack_type == 'quick_attack':
x = 10
else:
x = 60
return x
def escape(self):
return 0
pikachu_1 = Pikachu()
pikachu_2 = Pikachu(90)
クラスは設計書である。あるクラスに従ってオブジェクトを生成したとき、そのオブジェクトを、そのクラスのインスタンスとよぶ。例えば、下の例では pikachu_1
オブジェクトは、Pikachu
クラスのインスタンスであるという。インスタンスの属性を取得するときは、インスタンス名の後ろにピリオド .
を書き、その後ろの属性を付けて取得する。また、インスタンス中の関数を実行するとき、ピリオドの後に関数名を書く。このとき、この関数のことを、メソッドよぶ。右例の攻撃関数は、Pikachu の attack
メソッドという。
pikachu_1 = Pikachu(90)
pikachu_1.hp
# 90
pikachu_1.attack('quick_attack')
# 10
継承
ピカチュウだけであれば、ピカチュウのクラスがあれば足りる。しかし、すべてのポケモンカードを 1 つのクラスで実現させるためには、クラスの設計をもう少し変更する必要がある。そこで、一例として、変化する属性に着目して、右のように書き換えればよい。なお、攻撃技について、すべてのポケモンは攻撃可能だが、ダメージが異なるため、一括に定義できない。ここでは、攻撃技を定義するが、機能を付けないことにする。
class Pokemon:
def __init__(self, name, hp, type):
self.name = name
self.hp = hp
self.type = type
def attack(self):
pass
def escape(self):
return 0
p1 = Pokemon('Mew', 80, 'psychic')
p2 = Pokemon('Pikachu', 90, 'electric')
p3 = Pokemon('Ho-oh', 130, 'normal')
Pokemon
クラスでは、すべてのポケモンに共通する属性を定義できたものの、ポケモン間で異なっている攻撃技の動作を詳細に定義できなかった。そこで、Pokemon
クラスを基礎にして、Pokemon
クラスの攻撃技を書き換えて(オーバーライド)して、新しいクラスを設計してみる。例えば、ピカチュウについては、Pokemon
クラスの設計図に、攻撃技をオーバーライドすればよいので、右のようにかける。
class Pikachu(Pokemon):
def __init__(self, name, hp, type):
super().__init__(name, hp, type)
def attack(self, attack_type):
if attack_type == 'quick_attack':
x = 10
else:
x = 60
return x
pika = Pikachu('Pikachu 1', 90, 'electric')
pika.name
# 'Pikachu 1'
pika.hp
# 90
pika.attack('quick_attack')
# 10