どうも~むるむるです~
今回の記事では「クラス:class,コンストラクタ,継承など」について学んでいきたいと思います.
このシリーズではプログラミング初心者が最低限のPythonの知識を最短で身に着けることを目標としています.
このシリーズでは以下の順番でPythonの基本的な知識を学習していきます.
- Python:Anacondaインストールとhello world,簡単な計算,コメントアウト
- 変数について
- データ型:int, float, str, bool
- データ型:list, tuple, dict
- 条件分岐:if – else 文
- 繰り返し:for文,while文
- 関数の定義,呼び出し,ラムダ式
- クラス (この記事)
- モジュールのインポート
- 例外処理:try, except, else, finally
- map, reduce, filter
さて,早速本題に入りましょう.
クラスという概念は様々なプログラミング言語で使われ,プログラミング初学者を混乱させる概念のうちの一つです.
クラスをしっかり理解するにはオブジェクト指向を理解することが重要となりますが,これを完璧に理解するには,一つの記事では到底足りません.
この記事では完璧にオブジェクト指向を完璧に理解することは目的とせず「こういう考え方があってPythonではこうやって使えるんだ」程度の理解を目標にしています.
オブジェクト指向はコードをたくさん書いて経験を積んでからの方が理解しやすいと思うので,初心者を対象とするこのシリーズではなんとなく雰囲気だけ掴んでくれれば十分です.
オブジェクト指向の気持ち
オブジェクト指向の「オブジェクト」とは英語で「モノ」のことです.この世の中のものはすべてもモノ,すなわちオブジェクトとその組み合わせでできていると考えることができます.
例えば,ノートパソコンというモノはスクリーンやキーボードなどのモノの組み合わせで構成されているし,そのスクリーンやキーボードももっと小さい部品のモノの組み合わせで構成されています.
オブジェクト指向では,このモノ,つまりオブジェクト主体の考え方をプログラミングに応用したものです.すなわちオブジェクト指向はプログラムをすべてオブジェクトとオブジェクトの組み合わせで表現しようとしています.
そして,その大事なオブジェクトを作るための設計図のようなものがクラスになります.
説明ばかりでは余計わかりにくいと思うので,実際にPythonでクラスがどう使われるのか見ていきましょう.
クラス
クラスはPythonでは以下のようにして定義できます.
クラスの中身
クラスの中身の部分には,具体的にはそのクラスのもつ変数や関数を書いていきます.
このとき,クラスのもつ関数のことをメソッドといいます.例を見てみましょう. クラス名は通常,大文字から始めます.
class Robot:# クラス def hi(self):# メソッド print('Hi') robo1 = Robot()# インスタンス化 robo1.hi()
さて,今あなたはロボットエンジニアでロボットをプログラムしたいとしましょう.
上の例では「Robot」クラスというクラスを作りました.そのロボットクラスは「hi」というメソッド(そのクラスの関数)を持っています.引数となっている「self」に関しては後程説明するので今は決まり文句だと思っていてください.
あなたは今「Robot」クラスという設計書から実際のロボットである「robo1」というオブジェクトを作り出したのです.このようにクラスから実際のオブジェクトを作り出すことを「インスタンス化」といい,そのオブジェクトのことをインスタンスと言います.
そして 「Robot」クラスから作り出された「robo1」インスタンスは,メソッド「hi」を持っており一番最後の行では,「robo1」が,そのhiメソッドを呼び出しています.インスタンスからメソッドを呼び出すには以下のようにします.
さて,これであなたは「’Hi’」と挨拶のできるロボットを作ることに成功しました.
コンストラクタ
さて,挨拶のできるロボットを作れるようになったあなたは,ロボット(のインスタンス)を作る時にロボットに名前を付けたくなったとします.そんなときにつかえるのが「コンストラクタ」です.
コンストラクタは以下のようにクラスの中に「def __init__(self, …):」と定義します.
def __init__(self, 引数):# コンストラクタ
コンストラクタの中身
以下のコードでは「コンストラクタ」を使って,ロボットを作ったとき(インスタンス化したとき)に名前が付けられるようになっています.
class Robot:# クラス def __init__(self, name):# コンストラクタ self.name = name def hi(self):# メソッド print('Hi') def say_name(self):# メソッド print('My name is ' + self.name) alice = Robot('Alice')# インスタンス化 bob = Robot('Bob')# インスタンス化 alice.say_name()# メソッドの呼び出し print(bob.name)# インスタンスの持つ変数へアクセス ''' 出力結果: My name is Alice Bob '''
上の例ではインスタンス化するときに文字列を与えロボットに名前を付けています.上の「def __init__(self, name)…」の部分はコンストラクタと呼ばれ,クラスをインスタンス化した時に一度だけ呼ばれる関数になります.(注:initは二つのアンダースコア(_)に挟まれています.)
そして先ほどから出てきている「self」ですが,この「self」は,そのインスタンス自身のことです.
「alice」をインスタンス化したときになにが起きているかというと,コンストラクタが呼ばれ「’Alice’」という文字列が渡されます.そして「self.name = name」のところで,そのインスタンス自身,つまり「alice」のもつ変数として「name」が「’Alice’」に代入されたのです.
Pythonでクラスを書くときは,そのメソッドの一番初めに引数として「self 」を書くのが決まりになっています.
また,「bob.name」ではインスタンスの持つ変数にアクセスをしています.インスタンスのもつメソッドにアクセスするときと同様,「インスタンス名.変数名」とすることでインスタンスの持つ変数にアクセスができます.
クラス変数とインスタンス変数
さて,あなたが作るロボットにすべて共通している変数があったとします.例えばあなたが作れるロボットの足の本数と腕の本数は2本しかないとしましょう.以下の―コードを見てください.
class Robot:# クラス n_arms = 2# クラス変数 n_legs = 2# クラス変数 def __init__(self, name):# コンストラクタ self.name = name# インスタンス変数 def hi(self):# メソッド print('Hi') def say_name(self):# メソッド print('My name is ' + self.name) alice = Robot('Alice')# インスタンス化 bob = Robot('Bob')# インスタンス化 print(alice.n_arms)# インスタンスの持つ変数へアクセス print(bob.n_arms)# インスタンスの持つ変数へアクセス ''' 出力結果: 2 2 '''
上ではコンストラクタの前に変数「n_arms」と「n_legs」を定義しています.これは先ほどの「self.name」と違い同じクラスであれば,すべてのインスタンスが共通でもっている変数になります.
このような変数のことをクラス変数,そして先ほどの「self.name」 のようにインスタンスごとに値が異なるような変数をインスタンス変数と言います.
継承
さぁ,ロボットエンジニアとして成長したあなたは今あるロボットをつくる設計書(クラス)をもとにネコ型ロボットをつくりたいです.
猫型ロボットクラスには,ロボットクラスの変数やメソッドをそのまま引き継がせたうえで,独自の変数やメソッドを持たせたいとします.
そんな時に使うのがクラスの継承という考え方です.クラスの継承は以下のようにしてできます.
新しいクラスの中身
このとき継承されるクラスをスーパークラスや親クラスと呼び,スーパークラスを継承する新しいクラスのことをサブクラスや子クラスと呼びます.
早速例を見てみましょう.
class Robot:# 親クラス n_arms = 2 n_legs = 2 def __init__(self, name):# コンストラクタ self.name = name def say_name(self):# メソッド print('My name is ' + self.name) class CatRobot(Robot):# 子クラス def dokodemo_door(self): print('どこでもドア~') doraemon = CatRobot('ドラえもん') doraemon.say_name() doraemon.dokodemo_door() ''' 出力結果: My name is ドラえもん どこでもドア~ '''
このとき「CatRobot」がサブクラスとなりスーパークラスの「Robot」を継承しています.
「CatRobot」のインスタンスである「doraemon」は「Robot」クラスのsay_nameメソッドと「CatRobot」クラスのdokodemo_doorメソッドのどちらも呼び出せてることがわかると思います.
確認クイズ
以下の質問に答えてください.
- クラスとインスタンスの関係は?
- コンストラクタってなに?
- 継承とは?
- スーパークラスとサブクラスの関係は?
- クラス変数とインスタンス変数の違いは?
次回
次回は「モジュールのインポート」について学習します.
次の記事はこちら.
機械学習のためにしっかりとPythonを勉強したいなら,ある程度の基礎を身に着けた後に下の本を読むのがお勧めです.この本をこなせば,より高いレベルへ到達できるでしょう.