ドローンを使ってクラスやインスタンスを解説




クラスをつくってインスタンス化（そのときコンストラクタで初期化）してメソッドを呼び出すという流れになるわけですが、そもそもなんでこの流れになるのか、わからない人向けの記事です。

クラスやインスタンス、コンストラクタはわかりにくいですね。
理由はイメージしにくいからだと思います。
そこで目に見えるようドローンを使った例え話で解説します。
ドローンは単に時流に乗っただけですが、たい焼きや犬猫の例え話よりは、わかりやすいのではないかと。


さてドローンが作られて実戦に投入されるまでを考えてみると

①まず、ドローンには設計図があります
![c1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411052/bbcc8538-bdff-3e9e-6212-109e347e8256.jpeg)


②この設計図をもとに工場で大量生産します
	１号機、２号機、３号機。。。。100号機といった具合
![c2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411052/196a2763-1f87-f5fb-01df-cb4bfd196a9c.jpeg)

③ドローンは偵察に使う用途が多いですが、このドローンは自爆型とします。
　それぞれが戦場に運ばれ、別々のターゲットを狙うことになります。
　たとえば1-4号機にターゲットをセットするとこんな感じ
	１号機：戦車Aを狙う
	２号機：戦車Bを狙う
	３号機：トラックを狙う
	４号機：対空自走砲を狙う
![c3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411052/178dcae0-5143-a879-5b56-908f73febaef.jpeg)


④ドローンが発射されるとそれぞれが別々のルートを辿って、セットされたターゲットに接近します。
	その結果たとえばこんな結果になったとします
	
	１号機：戦車Aに見事命中
	２号機：戦車Bに惜しくも逃げられて、命中せず
	３号機：トラックは逃げたが、ドローンが軌道修正して見事命中
	４号機：対空自走砲に撃ち落とされた
![c4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411052/e0594cdc-52af-6e3a-a120-6dde6b3cbb07.jpeg)

同じ設計図からできあがったドローンが、違ったルートをたどって、まったく違った最後を迎えます。
それぞれの各ドローンが、それぞれの人生を歩むという感じです。

また、一度発射されたら人間の手を介さず、ドローンが自律的に（ひとりでに）動いていきます。
この「ひとりでに」というのがクラスをつかったプログラムの本質だと考えています。
以上のたとえ話を、そっくりそのままクラスとインスタンス、コンストラクタにあてはめてみましょう。

## ①クラス
まず設計図はクラスそのもの、クラスはよく設計図に例えられるので一度くらいは聞いたことがあると思います。

## ②インスタンス
できあがったドローンは製品そのものですが、プログラムではインスタンスに相当します。インスタンスは実体です。
	インスタンスは１つ、２つでも１０００個、２０００個でもメモリが許す限り大量生産できます。
	繰り返しますが、クラスは設計図なのに対して、インスタンスは実体です。
	ドローンのたとえでインスタンスに該当するのは、ものとしてちゃんと飛ぶし、製造番号なども貼られたドローンの機体そのものです。

## ③コンストラクタ
各インスタンスに初期設定をします。これはコンストラクタと呼ばれます。ドローンの例え話では１機１機、別々のターゲットに狙いを定めました。

## ④メソッド呼び出し
実体としてのインスタンスはそれぞれ別のライフサイクルを歩み、自律的に動きます。
	自律的と言ってもコンピュータの擬似的な環境の中で行われます。
	たとえばループする中で、クラスの関数であるメソッドを呼び出し続けるとか、
	あるいはイベントが発生したときにメソッドを呼ぶなどといった方法で、自律っぽい動きをさせます。

ポイントは各インスタンス（ドローン）は大量生産されて、それぞれ初期設定をされて、自律的に動き別々のライフサイクルを歩むということです。



# コードの書き方
## ①クラス
	class クラス名():
		#コンストラクタの中でインスタンス変数
		#メソッド1
		#メソッド2
		#メソッド3
	メソッドは関数のことです。

## ②インスタンス化
	変数名 = クラス名(引数)	
		引数は初期設定用です

## ③コンストラクタ
    def __init__(self,引数):
        self.変数1 = 初期値
        self.変数2 = 引数

## ④変数名.メソッド名()で関数を呼び出す



具体的なコードに落とし込んでみました。

#シンプル版
	簡単なのため移動はｘ軸方向のみとし、1tick(単位時間)で1だけ移動します。
	4,5,8,11の位置に止まっている4台の敵車両を狙います

```py

import time

#設計図
class Drone():				#クラス名がDrone
    def __init__(self,tx):	#コンストラクタ
        self.x = 0			#ドローンの現在位置（最初はゼロ）
        self.tx = tx 		#ターゲット位置
    
    def move(self):			#メソッド名
        self.x += 1			#ｘ軸方向に移動
        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)			#１秒待ち
    tick += 1
    if tick > 12:			#tickは12で終了とします
        break
```
結果：
●1tick
●2tick
●3tick
●4tick
　起爆
●5tick
　起爆
●6tick
●7tick
●8tick
　起爆
●9tick
●10tick
●11tick
　起爆
●12tick



# 命中確率を組み込む
例えば、戦車だと確率40%、トラックは80%で命中、逆に対空自走砲の場合80%で撃墜されるみたいなことを組み込んでみます。

```py
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)#１秒待ち
    tick += 1
    if tick > 12:
        break

```    

実行結果
●1tick
●2tick
●3tick
●4tick
  戦車　起爆
 　外れ
●5tick
  戦車　起爆
 　命中
●6tick
●7tick
●8tick
  トラック　起爆
 　命中
●9tick
●10tick
●11tick
  対空自走砲　起爆
 　撃墜
●12tick

# バッテリー切れを組み込む
悪ノリでバッテリー切れも組み込んでみました。
10tick以上はバッテリー切れで墜落とします

```py
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)#１秒待ち
    tick+=1
    if tick> 12:
        break
```
結果：    

●1tick
●2tick
●3tick
●4tick
　戦車起爆
 　命中
●5tick
　対空自走砲起爆
 　撃墜
●6tick
●7tick
●8tick
　トラック起爆
 　命中
●9tick
●10tick
●11tick
 　バッテリー切れ墜落
●12tick