[光-Hikari-のPython]09章-02クラス（クラスの作成とインスタンス化）

#[Python]09章-02 クラスの作成とインスタンス化
前節では、オブジェクトとは何かについて説明し、数値やリストなどはすべてオブジェクトであると説明しました。例えば、数値型オブジェクトやリスト型オブジェクトといったものです。

今回は自分自身でオブジェクトを作成する方法について触れていきたいと思います。

##オブジェクトの設計図とは
Pythonでは、数値型やリスト型、文字列型のオブジェクトがあると説明しました。
例えば、文字列型オブジェクトであれば「データの先頭だけを大文字にする」「データの中で指定した文字を探す」といった動作（メソッド）があります。

これは、文字列型のオブジェクトですが、実はこの文字列型のオブジェクトの**設計図**がPython内に存在します。（普段は意識していないですが）
この設計図に当たるのが**クラス**と言われるものです。

今まで数値や文字列、リストなどについて無意識に使ってきましたが、これを使うたびに**設計図（クラス）に基づいてオブジェクトを生み出しているのです。**

この設計図には、例えば**データ（属性またはプロパティともいう）はどうするか**、**メソッドはどう処理するか**といった内容が書かれています。

以下はオブジェクトの設計図でクラス図<font color=orange>（※）</font>と言い、プログラミングの設計時によく使われる図です。

例えば以下のクラス図の例は、人（Person）を表す設計図です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/e340e789-2984-8c2c-8113-6e6c16c5a31c.png)

<font color=orange>（※）</font>クラス図は、UML（Unified Modeling Language）の基本となる図の1つで、本来はシステムを構成するクラスの関連を表現することが多く、さらにクラスが保持する属性とメソッドを示します。


##クラスの作成
さて、いよいよクラスを作成し、オリジナルのオブジェクトを作成していきたいと思います。
まず、一般的には以下のように、記述していきます。

```.py
class クラス名:
    クラスを定義するコンストラクタやメソッド
```
いくつか聞いたことない用語もありますが後ほど説明しますが、:（コロン）の下に、先ほどのクラス図の中身を記載していくことになります。

とはいっても、いきなり一般的なことは難しいので、ここでは鳥（Bird）を表すクラス定義の例を用いてを説明します。
以下のデータ（属性）とメソッドを持つことを前提に、Bird型のオブジェクトプログラムを作成してみましょう。
**【属性】**
・名前（name）
・色（color）

**【メソッド】**
・飛ぶ動き（fly）メソッド
・鳥のステータスを出力する（print_status）メソッド

まずはこれをクラス図で表してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/aef03b32-742d-6b71-a3b9-ad5ab14d6776.png)


まずはBird型のクラスから作成してみましょう。<font color="#00cccc">chap09</font>の中に<font color="#00cccc">samp09_03_01.py</font>を作成し、以下のコードを書いてください。
<font color=red>※</font>今回から、samp09-02-01.pyでなく、**samp09_02_01.py**という_（アンダースコア）を使った表記で名前付けします。

```.samp09_02_01.py
class Bird:
    def __init__(self, name, color):
        print('-----インスタンス化したと同時にコンストラクタを呼び出します。-----')
        self.name = name
        self.color = color

    #飛ぶというメソッド
    def fly(self, m):
        print('-----flyメソッドを呼び出します。-----')
        print(f'バサバサと{self.name}は空を飛びます。')
        print(f'{m}mの高さを飛んでいます。')

    #インスタンス化したBirdのステータスを出力するメソッド
    def print_status(self):
        print('-----print_statusメソッドを呼び出します。-----')
        print(f'{self.color}色の鳥です。')
```

さて、先ほどのクラス図と一緒で「飛ぶメソッド（fly）」と「ステータスを表示するメソッド（print_status）」このプログラムを実行してみましょう。しかし、何も表示されないことを確認できます。

これを解決するには、**インスタンス化**が必要となります。

##インスタンス化
今、上のプログラムで実行結果が表示されませんでしたが、上のプログラムではBirdクラス、つまり**Birdという型の設計図を作っただけ**です。この段階ではまだ「鳥（Bird）はこういうものである」という型を定義したのみで、具体的な鳥の実体は存在していないことになります。
（例として、タイ焼きの型は定義しているが、タイ焼き自体はできていない状態）

この設計図から実体化する必要があり、これを**インスタンス化**といいます。さらに実体化したものを**インスタンス**といいます。

インスタンス化するには以下のコードを追加する必要があります。<font color="#00cccc">samp09_02_01.py</font>に以下のコードを追記してください。


```.samp09_02_01.py
class Bird:
    def __init__(self, name, color):
        print('-----インスタンス化したと同時にコンストラクタを呼び出します。-----')
        self.name = name
        self.color = color

    #飛ぶというメソッド
    def fly(self, m):
        print('-----flyメソッドを呼び出します。-----')
        print(f'バサバサと{self.name}は空を飛びます。')
        print(f'{m}mの高さを飛んでいます。')

    #インスタンス化したBirdのステータスを出力するメソッド
    def print_status(self):
        print('-----print_statusメソッドを呼び出します。-----')
        print(f'{self.color}色の鳥です。')


#インスタンス化するときに鳥の名前と色を指定し、chiという変数に代入
chi = Bird('チッチ', '茶')
```
こうすることで、鳥（Bird）のインスタンスができ、図で表すと以下の通りになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/80c63d49-6f11-43df-376a-3d207e16aea2.png)

**chi**という変数（以前にタグと説明しました）を持つBirdです。

##コンストラクタ
プログラムにもコメントで記載がありますが、**def \_\_init\__(self, name, color):**という個所を**コンストラクタ**と言います。

実はこのコンストラクタがないと、インスタンス化したときに**name**（今回は「チッチ」）と**color**（今回は「茶」）というデータ（属性）が反映されなくなってしまいます。

そこで、インスタンス化することで同時にデータ（属性）を反映させるために、コンストラクタ内で値を**name**と**color**それぞれに反映させます。

気になる、この**self**ですが、実は**インスタンス自身を示して**おり、**第一引数**ということがあります。（selfという名前でなくてもよいのですが、慣習としてselfということが多いです。）
なので、コンストラクタ内の、「self.name = name」というのは、**「インスタンス自身のname」**に**「name（実際に「チッチ」という値が入っている）」**を代入しているのです。

そうすることで、インスタンス化した鳥（Bird）に以下のように属性を持たせることが可能です。
<font color=red>※</font>色（color）が「茶」、名前（name）が「チッチ」であることを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602679/7a6dfe5a-83e4-d20c-8618-af0e366c599d.png)

##インスタンス化したものを操作する
ここまでは、Bird型のクラスを作成し、インスタンス化することでオブジェクトができました。
前節でお話しした通り、**オブジェクトにはデータ（属性）とメソッドを持っているものであると説明**しました。
今回はどうでしょう？Bird型オブジェクトには**name**と**color**という属性、**fly()**と**print_status()**というメソッドを持っています。

では、それらを実際に操作してみましょう。先ほどのプログラムに追記してください。（追記は最後のほうです）

```.samp09_02_01.py
class Bird:
    def __init__(self, name, color):
        print('-----インスタンス化したと同時にコンストラクタを呼び出します。-----')
        self.name = name
        self.color = color

    #飛ぶというメソッド
    def fly(self, m):
        print('-----flyメソッドを呼び出します。-----')
        print(f'バサバサと{self.name}は空を飛びます。')
        print(f'{m}mの高さを飛んでいます。')

    #インスタンス化したBirdのステータスを出力するメソッド
    def print_status(self):
        print('-----print_statusメソッドを呼び出します。-----')
        print(f'{self.color}色の鳥です。')


#インスタンス化するときに鳥の名前と色を指定し、chiという変数に代入
chi = Bird('チッチ', '茶')

#Bird型オブジェクトのflyメソッドを呼び出す
chi.fly(15)

#Bird型オブジェクトのprint_statusメソッドを呼び出す
chi.print_status()
```
><font color="#090" bgcolor="black">【実行結果】</font>
-----インスタンス化したと同時にコンストラクタを呼び出します。-----
-----flyメソッドを呼び出します。-----
バサバサとチッチは空を飛びます。
15mの高さを飛んでいます。
-----print_statusメソッドを呼び出します。-----
茶色の鳥です。

まず、クラス（Bird）の処理を通過し、

```.py
chi = Bird('チッチ', '茶')
```
によりインスタンス化しています。これにより、chiという値にBird型オブジェクトが作成されます。同時にコンストラクタにより
**「-----インスタンス化したと同時にコンストラクタを呼び出します。-----」**
と出力した後、**name**と**color**の値が代入されます。

次に、

```.py
chi.fly(15)
chi.print_status()
```

により、chiというBird型オブジェクトの動作をそれぞれ呼び出しています。

といっても、パッとしずらいので少し以下のように考えてみましょう。リスト型のオブジェクトと今回作成したBird型のオブジェクトを比較して考えてみます。

|  | リスト型のオブジェクト | Bird型のオブジェクト |
|:-:|:-:|:-:|
| インスタンス作成  | ls = [10, 15, 20]  | chi = Bird('チッチ', '茶')  |
|  この時の属性（データ） | 10, 15, 20  |  'チッチ', '茶' |
| オブジェクト内の<br>何かしらのメソッド実行1  | ls.count(10)<br>（10という数値がいくつあるか調査するメソッド）  |chi.fly(15)<br>（飛ぶ命令を出力し、高さも出力するメソッド）   |
|  オブジェクト内の<br>何かしらのメソッド実行2  |  ls.clear()<br>（リスト内の要素を削除するメソッド） |  chi.print_status()<br>（ステータスを出力するメソッド） |

##型を調べる
上記の例では、**chi**が**Bird型のオブジェクト**であると説明しましたが、本当にそうなのかを調べることもできます。
今回は**Python Console**から以下のコードを入力してみましょう。

```.py
>>> from chap09.samp09_02_01 import Bird
>>> chi = Bird('チッチ', '茶')
-----インスタンス化したと同時にコンストラクタを呼び出します。-----
>>> type(chi)
<class 'chap09.samp09_02_01.Bird'>
```
確かに、Bird型のオブジェクトであることがわかりました。（保存してあるフォルダやプログラム名により変わることはありますが、Birdオブジェクトであることには変わりはありません。）

##最後に
クラスという設計図からインスタンス化をする方法について説明しました。今回は説明しなかったのですが、1つの設計図からいくつもインスタンス（≒オブジェクト）を作成することは可能です。

今回は**chi**という変数にインスタンス化したものを代入しましたが、実際に変数を変えたりして、違う名前や色の鳥も複数作成してみましょう。

オブジェクトについては、難しいこともありますが、今まで利用してきたメソッド・関数を用いていることには変わりはありません。先ほどの表と比べてみながら考えるとわかりやすいと思われます。

###[【目次リンク】へ戻る](https://qiita.com/ko0821/items/379e8bd9e6ea01089419)