それは医者も同じ・・・
Pythonでクラスを勉強するといきなり
インスタンス、プロパティ、メソッド
といった言葉が出てきて挫折します。私もそうでした。
ここではクラス、インスタンス、プロパティ、メソッドを直感的にわかりやすいように説明したいと思います。
クラスとは
Pythonで扱うデータの種類です。
「文字列」「数値」「リスト」「辞書型」などもクラスの一種です。
性質を持った「もの」を「インスタンス」と呼びます。
ここでは
「Pythonのクラスの用語をドラクエ的なRPGゲームに例えて」
説明します。
クラスは職業、インスタンスは登場人物
ゲームではいろいろな能力をもったキャラクターが出てきます。
能力を持つ職業として、
戦士”warrior”と 魔法使い”magician”
があるとします。 それぞれ異なる特技を持っています。
この
戦士”warrior”, 魔法使い”magician”
という
職業がクラスにあたります。
さて、
“mike”という名前のキャラクターを戦士”warrior”
に設定してゲームに登場させます。
戦士”warrior”の初期値を単純に
体力 hp : 50
力 power : 10
と設定します。
ここまでをスクリプトで説明していきます。
class warrior():
# warriorというクラスを設定
def __init__(self):
#まず初期値を設定する
self.hp = 50
# 初期 hp は50
self.power = 10
# 初期 power は10
ここまでが職業 戦士”warrior”の設定です。
初期値は__init__(self)で定義しています。
ここでmikeを戦士”warrior”として登場させます。
mike = warrior()
# mikeをwarriorとして登場させる
この登場人物mikeを「インスタンス」と呼びます。
一般化して言うと、
「設定したパラメータを持った変数」
です。
プロパティは登場人物のステータス
ここで初期値を確認します。
mike.hp
# 50
mike.power
# 10
という具合に
インスタンス.(パラメータ)
でそのインスタンスのもつパラメータ値が呼び出されます。
このパラメータが
「プロパティ」
です。
RPGゲームのステータスみたいなものですね。
ここでもう一つのクラス、魔法使い”magician”を定義し、
tomという名前のキャラクターを魔法使いとして登場させます。
初期値は戦士”warrior”と異なり、
hp(体力) : 30
mp(マジックポイント) : 20
magic (魔力) : 5
としておきます。
スクリプトで書くと
class magician():
def __init__(self):
self.hp = 30
self.mp = 20
self.magic =5
となります。
tomを魔法使い”magician”として登場させます。
tom = magician()
tom.hp
# 30
tom.mp
# 20
warriorと違う初期値が入っていることがわかります。
ここで魔法使いmagicianのpowerを見ようとすると
In [12]: tom.power
—————————————————————————
AttributeError Traceback (most recent call last)
—-> 1 tom.power
AttributeError: ‘magician’ object has no attribute ‘power’
「そんなプロパティはありません」
と出力されます。
メソッドは登場人物の攻撃や魔法といった特技
メソッドとは
「そのクラスが実行できる処理のことです。」
RPGゲームでいうと、「攻撃」「魔法」
などです。
例として、先程のwarrior戦士とmagician魔法使いが戦うとしましょう。
戦士warriorは攻撃”attack”で
「相手に自分の力”power”と同じダメージを与えられる」
とします。
ダメージは「体力”hp”の減少」になります。
この攻撃”attack”が
「メソッド」
に当たります。
戦士”warrior”が攻撃”attack”できるよう、class warrior内に “attack”を定義します。
class warrior():
def __init__(self):
self.hp = 50
self.power = 10
#メソッド 攻撃attackを定義する。
def attack(self, target): #target : 相手の名前
target.hp = target.hp - self.power
#ダメージとして相手のhpから自分のpowerの値を引く
メソッドattackを実行すると
このdef attack以下に指定した処理が行われます。
この上で
mikeを戦士”warrior”, tomを魔法使い”magician”に設定し、tomに対してattackメソッドを実行します。
mike = warrior()
tom = magician()
print(tom.hp)
# 30
mike.attack(tom)
print(tom.hp)
# 20
tomの体力”hp”がmikeの攻撃力”power”の分 10 だけ減っています。
同様に魔法使い”magician”は、魔法”fire”メソッドで相手を攻撃できるとします。
「相手のダメージは魔力magic powerの3倍」
とします。同時にこのメソッドを使用すると
「マジックポイントmpが3減る」
とします。
まずはメソッド”fire”を定義します。
class magician():
def __init__(self):
self.hp = 30
self.mp = 20
self.magic =5
def fire(self, target): #targetには相手の名前が入る
target.hp = target.hp - self.magic * 3
# ダメージとして相手hpから自分のmagicの3倍を引く
self.mp = self.mp - 3
# 自分のマジックポイントを3消費
そして、tomがメソッド「fire」をmikeに向かって使用します。
tom.fire(mike)
print(mike.hp)
#35
print(tom.mp)
#17
ちゃんとダメージを与えてmpが消費しています。
warriorのmikeにfireを使用させようとしても使えません。
In [31]: mike.fire(tom)
—————————————————————————
AttributeError Traceback (most recent call last)
—-> 1 mike.fire
AttributeError: ‘warrior’ object has no attribute ‘fire’
warriorクラスにはfireメソッドが指定されていません。
と出ます。
「戦士は魔法がつかえない」
というやつですね。
エラーメッセージにはここでもattributeと出ています。
AttributeErrorはメソッドがない場合、プロパティがない場合を両方ひっくるめて表示されることがわかります。
ここまでの処理を進めた段階で、インスタンス tom, mikeともに、そのプロパティは初期値から書き換えられています。
print(mike.hp)
# 35
print(tom.hp, tom.mp)
# 30 17
同じクラスの新たなインスタンスをどんどん作成できる
ここで新たにwarriorとしてtaro, magicianとしてhanakoを登場させます。
taro = warrior()
hanako = magician()
同じクラスのインスタンスをどんどん作成できます。
ドラクエでいうと「ルイーダの酒場」ですね。
新しく呼び出したインスタンスは
print(taro.hp)
# 50
print(hanako.hp, hanako.mp)
# 30 20
__init__以下が読み込まれて初期値が設定されるので、まっさらな状態のインスタンスとして登場することができます。
ドラクエなどのRPGゲームでクラスの用語を例えると
- インスタンスは登場人物(名前が変数名)
- クラスは職業など持っている能力
- プロパティは体力、攻撃力などのステータス
- メソッドは攻撃、魔法などの特技
- アトリビュート(属性)はプロパティとメソッド両方を指す