クラスをつくってインスタンス化(そのときコンストラクタで初期化)してメソッドを呼び出すという流れになるわけですが、そもそもなんでこの流れになるのか、わからない人向けの記事です。
クラスやインスタンス、コンストラクタはわかりにくいですね。
理由はイメージしにくいからだと思います。
そこで目に見えるようドローンを使った例え話で解説します。
ドローンは単に時流に乗っただけですが、たい焼きや犬猫の例え話よりは、わかりやすいのではないかと。
さてドローンが作られて実戦に投入されるまでを考えてみると
②この設計図をもとに工場で大量生産します
1号機、2号機、3号機。。。。100号機といった具合
③ドローンは偵察に使う用途が多いですが、このドローンは自爆型とします。
それぞれが戦場に運ばれ、別々のターゲットを狙うことになります。
たとえば1-4号機にターゲットをセットするとこんな感じ
1号機:戦車Aを狙う
2号機:戦車Bを狙う
3号機:トラックを狙う
4号機:対空自走砲を狙う
④ドローンが発射されるとそれぞれが別々のルートを辿って、セットされたターゲットに接近します。
その結果たとえばこんな結果になったとします
1号機:戦車Aに見事命中
2号機:戦車Bに惜しくも逃げられて、命中せず
3号機:トラックは逃げたが、ドローンが軌道修正して見事命中
4号機:対空自走砲に撃ち落とされた
同じ設計図からできあがったドローンが、違ったルートをたどって、まったく違った最後を迎えます。
それぞれの各ドローンが、それぞれの人生を歩むという感じです。
また、一度発射されたら人間の手を介さず、ドローンが自律的に(ひとりでに)動いていきます。
この「ひとりでに」というのがクラスをつかったプログラムの本質だと考えています。
以上のたとえ話を、そっくりそのままクラスとインスタンス、コンストラクタにあてはめてみましょう。
①クラス
まず設計図はクラスそのもの、クラスはよく設計図に例えられるので一度くらいは聞いたことがあると思います。
②インスタンス
できあがったドローンは製品そのものですが、プログラムではインスタンスに相当します。インスタンスは実体です。
インスタンスは1つ、2つでも1000個、2000個でもメモリが許す限り大量生産できます。
繰り返しますが、クラスは設計図なのに対して、インスタンスは実体です。
ドローンのたとえでインスタンスに該当するのは、ものとしてちゃんと飛ぶし、製造番号なども貼られたドローンの機体そのものです。
③コンストラクタ
各インスタンスに初期設定をします。これはコンストラクタと呼ばれます。ドローンの例え話では1機1機、別々のターゲットに狙いを定めました。
④メソッド呼び出し
実体としてのインスタンスはそれぞれ別のライフサイクルを歩み、自律的に動きます。
自律的と言ってもコンピュータの擬似的な環境の中で行われます。
たとえばループする中で、クラスの関数であるメソッドを呼び出し続けるとか、
あるいはイベントが発生したときにメソッドを呼ぶなどといった方法で、自律っぽい動きをさせます。
ポイントは各インスタンス(ドローン)は大量生産されて、それぞれ初期設定をされて、自律的に動き別々のライフサイクルを歩むということです。
コードの書き方
①クラス
class クラス名():
#コンストラクタの中でインスタンス変数
#メソッド1
#メソッド2
#メソッド3
メソッドは関数のことです。
②インスタンス化
変数名 = クラス名(引数)
引数は初期設定用です
③コンストラクタ
def __init__(self,引数):
self.変数1 = 初期値
self.変数2 = 引数
④変数名.メソッド名()で関数を呼び出す
具体的なコードに落とし込んでみました。
#シンプル版
簡単なのため移動はx軸方向のみとし、1tick(単位時間)で1だけ移動します。
4,5,8,11の位置に止まっている4台の敵車両を狙います
import time
#設計図
class Drone(): #クラス名がDrone
def __init__(self,tx): #コンストラクタ
self.x = 0 #ドローンの現在位置(最初はゼロ)
self.tx = tx #ターゲット位置
def move(self): #メソッド名
self.x += 1 #x軸方向に移動
if self.x == self.tx: #ターゲットの位置と一致したら爆発
print(" 起爆")
#main
dst = [4,5,8,11] #初期設定用データ(ターゲットの位置)
l = len(dst)
#実体化と初期設定
Ds = []
for i in range(l):
D = Drone(dst[i]) #インスタンス化
Ds.append(D) #リストに追加
#ループの中で時々刻々と変化する環境を作り出します
tick = 1
while True:
print("●"+str(tick)+"tick")
for D in Ds:
D.move() #メソッド呼び出し
time.sleep(1) #1秒待ち
tick += 1
if tick > 12: #tickは12で終了とします
break
結果:
●1tick
●2tick
●3tick
●4tick
起爆
●5tick
起爆
●6tick
●7tick
●8tick
起爆
●9tick
●10tick
●11tick
起爆
●12tick
命中確率を組み込む
例えば、戦車だと確率40%、トラックは80%で命中、逆に対空自走砲の場合80%で撃墜されるみたいなことを組み込んでみます。
import random
import time
#設計図
class Drone():
def __init__(self,tx,tn): #これが初期設定、インスタンス化のときに呼び出される関数
self.x=0
self.tx=tx #ターゲット位置
self.tn=tn #ターゲットの名前
def move(self):
r=random.randint(1,5) #疑似サイコロ
self.x+=1
if self.x== self.tx:
print(" "+self.tn+" 起爆")
if self.tn=="戦車":
if r>=4:
print(" 命中")
else:
print(" 外れ")
elif self.tn=="トラック":
if r>=2:
print(" 命中")
else:
print(" 外れ")
elif self.tn=="対空自走砲":
if r==5:
print(" 命中")
else:
print(" 撃墜")
#main
dst = [4,5,8,11] #初期設定用データ(ターゲットの位置)
type = ["戦車","戦車","トラック","対空自走砲"] #ターゲットの種類
l = len(dst)
#実体化と初期設定
Ds = []
for i in range(l):
D = Drone(dst[i],type[i]) #インスタンス化
Ds.append(D) #リストに追加
#内包表記の場合
#Ds=[Drone(dst[i],type[i]) for i in range(l)]
#時々刻々と変化する環境を作り出していきます
tick = 1
while True:
print("●"+str(tick)+"tick")
for D in Ds:
D.move()
time.sleep(1)#1秒待ち
tick += 1
if tick > 12:
break
実行結果
●1tick
●2tick
●3tick
●4tick
戦車 起爆
外れ
●5tick
戦車 起爆
命中
●6tick
●7tick
●8tick
トラック 起爆
命中
●9tick
●10tick
●11tick
対空自走砲 起爆
撃墜
●12tick
バッテリー切れを組み込む
悪ノリでバッテリー切れも組み込んでみました。
10tick以上はバッテリー切れで墜落とします
import random
import time
##設計図
class Drone():
def __init__(self,tx,tn):
self.x=0
self.tx=tx #ターゲット位置
self.tn=tn #ターゲットの名前
def move(self):
self.x+=1
if self.x== self.tx:
if self.x>10:
print(" バッテリー切れ墜落")
else:
r=random.randint(1,6)
print(self.tn+" 起爆")
if self.tn=="戦車":
if r>=4:
print(" 命中")
else:
print(" 外れ")
elif self.tn=="トラック":
if r>=1:
print(" 命中")
else:
print(" 外れ")
elif self.tn=="対空自走砲":
if r==6:
print(" 命中")
elif 2<=r<=5:
print(" 撃墜")
else:
print(" 外れ")
dst=[4,5,8,11]
type=["戦車","対空自走砲","トラック","トラック"]
l=len(dst)
#実体化と初期設定
Ds=[]
for i in range(l):
D = Drone(dst[i],type[i]) #インスタンス化
Ds.append(D) #リストに追加
tick=1
while True:
print("●"+str(tick)+"tick")
for D in Ds:
D.move()
time.sleep(1)#1秒待ち
tick+=1
if tick> 12:
break
結果:
●1tick
●2tick
●3tick
●4tick
戦車起爆
命中
●5tick
対空自走砲起爆
撃墜
●6tick
●7tick
●8tick
トラック起爆
命中
●9tick
●10tick
●11tick
バッテリー切れ墜落
●12tick