プログラミングを学ぶ上で、クラスの理解はさけて通れません。
しかし、クラスは抽象的な概念ですので、非常に理解しづらいです。
さらに、書籍やネット上での説明がクラスの理解を更に難しくしてしまっているように感じます。
そこでここでは、クラスについてしっかりと理解していくための情報を整理しました。
クラス=設計図、オブジェクト=実体という表現は一旦忘れる。
クラスの説明としてよく見かけるのが、クラス=設計図、オブジェクト=実体という考え方です。
この説明はある意味正しいのですが、これがクラスの理解を妨げる原因になっているように感じています。
私もこのような説明を受けたのですが、全く理解できなかったです。
ですので、クラスが設計図、オブジェクトが実体という考えは一旦捨てて、全く新しい気持ちでクラスについて学んでいきましょう。
Pythonにおけるクラスは、関数の延長線のようなものと考える
具体例を見ながらクラスへの理解を深めていきましょう。
まず、ここではクラスは関数と同じようなもの、と考えましょう。この意味について、具体的な例と共に考えていきます。
まず、関数について簡単に復習です。
関数の説明で、関数そのものと、関数の呼び出しは違うということをお伝えしました。
(この点について整理したい方は、関数という記事を読んでみて下さい。)
例えば、このような関数があったとしましょう。
コードdef plus():
print('hello')
return
この関数を呼び出すと、helloという文字列が表示されます。
ただ、b = plusというコードを実行すると(plusの後にかっこを付けないと)、bは関数自体を示します。つまり、関数は実行されていません。
実際に実行してみましょう。
コードprint(plus)
アウトプット<function plus at 0x.... >
これは、bという変数が、print('hello')などのコードを含んだplus()関数がメモリ上に格納されている番地を示している。と言うことができます。(厳密には番地ではないのですが、考え方としては番地で問題ありません。)
そして、b = plus()というコードを実行すると、関数が呼び出され、関数の中のコードが実行されるのです。
つまり、関数というのはコードのかたまりであり、()をつけて関数を実行することによって、中のコードを順次実行する。と言うことができます。
関数を意識しつつ、クラスについて考える
先程の関数の考え方を頭に置きつつ、クラスについて考えていきましょう。
クラスは関数と同じように定義することができます。
関数では、def plus():という形でしたが、クラスではclass Plus():という形で定義します。defがclassに変わっただけです。
ちなみに、クラスではPlusと先頭が大文字になっていますが、小文字でもPythonの文法上は問題ありません。
(実際にコードを書く際は、関数と区別するため、必ず大文字にしましょう。)
そして、関数と同じくインデントで行下げをします。
クラスの具体例をみていきましょう。
コードclass Plus():
print('hello')
pass
ここで、関数の場合と同じく、クラスを呼び出さずに(かっこをつけずに)変数に代入してみましょう。
コードb = Plus
このb = Plusというコードを実行するとどうなるでしょうか?
コードb = Plus
アウトプット<class '__main__.Plus>
と表示されたと思います。
つまり、関数の時に<class function>と表示されたように、クラスにおいても()を付けない場合、そのクラスに関連する情報が入っている場所のアドレスへの参照が作られました。
次に、b = Plus()というコードを実行するとどうなるでしょうか?
コードb = Plus()
アウトプットhello
helloという文字列が表示されました。
つまり、クラスを実行することによって、クラスのブロックに書かれているコードが実行されたのです。
この動きは、関数の場合と全く同じですよね。
そう考えると、関数とクラスが似ている、ということが分かるかと思います。
これが、関数とクラスは同じようなもの、とお伝えした理由です。
ただ、関数とクラスでは、それぞれが実現できることと、用途が全く違うのです。
ここから、クラスができることについて見ていきましょう。
クラスでできること
では、クラスはどのような特徴があり、何を実現することができるのでしょうか?
具体例とともに、クラスに対する理解を深めていきましょう。
オブジェクトを作る
まずは前提として知っておきたい知識についてです。
クラスの場合、以下のようにクラスを実行することを、オブジェクトを作成する。といいます。
コードb = Plus()
これは、bというオブジェクトを作成した。と言います。
オブジェクトの作成とともに実行される関数がある
ここから、クラスでできることの具体例を見ていきましょう。
このようなコードがあったとします。
コードclass Hello():
def __init__(self):
print('hello!')
return
ここで、オブジェクトを作るとどのような結果が得られるでしょうか。
コードb = Hello()
アウトプットhello!
オブジェクトを作っただけなのですが、helloという文字列が出力されました。言い換えると、__init__という関数が実行されました。
なぜ実行されたのかというと、__init__メソッドは、クラスからオブジェクトが作られた時、自動的に実行される関数として定義されているからです。
こういった特殊な関数などを使うことができるのが、クラスを使うメリットなのです。
Pythonのクラスでは、__init__など、特殊な役割を持つ関数が沢山あります。
普段はあまり意識しなくてもこれらの関数が使いやすいように整理されているのですが、こういった関数について理解を深めることが、プログラミングのスキルを向上させる上で非常に大切です。
クラスを使ったデータ管理
更に具体的な例で、クラスができることについて見ていきましょう。
社員の給与計算をするシステムを作る場合
社員の給与計算をするシステムを作る場合を例にして考えてみましょう。
この会社には、社員が1,000人います。そして、若手社員は基本給が30万円、中堅社員は基本給が40万円とします。
また、残業代は若手:残業時間x2,000円、中堅:残業時間x3,000円としましょう。
この時、200人の社員が若手で、800人の社員が中堅とした時、それぞれの給料をデータとして記録するためには、どのようにすれば良いでしょうか?
コードyoung_base = 300000 #若手の基本給の設定
middle_base = 400000 #中堅の基本給の設定
と、2つの変数を準備して、一人一人の社員にそれぞれの基本給をわりあてるという方法があります。
コードstaff1_base = young_base #社員1は若手の基本給
staff2_base = middle_base #社員2は中堅の基本給
staff3_base = young_base #社員3は若手の基本給
また、残業手当を計算する場合には、まず若手と中堅の残業代を変数として設定します。
コードyoung_late = 2000 #若手の残業代の設定
middle_late = 3000 #中堅の残業代の設定
そして、それぞれのスタッフ毎の残業時間をかけることによって、残業代を出します。
コードstaff1_late = young_late * 8 #社員1の残業代
staff2_late = middle_late * 10 #社員2の残業代
staff3_late = young_late * 11 #社員3の残業代
といった具合です。
こういったデータがどんどん増えていくと、管理の手間がどんどん増えていくことはイメージが付くのではないかと思います。
基本給の変更であれば元の変数をかえれば対応できますが、若手が中堅になった場合、基本給の部分と残業代の部分の2か所を変更しなければいけません。
データがふえればふえるほど、何か変更があった場合の対応が難しくなってしまうのです。
こういった時にクラスを使うと、スッキリと整理することができます。
上記の給与の計算の場合、まずは若手と中堅の2つのクラスを準備し、それぞれに基本給と残業手当を出します。
また、latetimeというのは社員の残業時間です。
コードclass Young():
base = 300000
def __init__(self, latetime):
latetime = 2000
latefee = latetime * 2000
class Middle():
base = 400000
def __init__(self, latetime):
latetime = 3000
latefee = latetime * 3000
このようなクラスを作ることで、以下のような形でそれぞれの社員のデータを管理することができます。
コードstaff1 = Young(8)
staff2 = Middle(10)
staff3 = Young(11)
staff1が若手から中堅社員になればYoungをMiddleに変えるだけで良いですし、元のデータ(基本給)が変更になった場合でも、元のデータだけを変えれば良いことが分かります。
クラスを使うことで、スッキリと情報を整理することができました。
便利な機能を少しずつ学んでいくと、クラスへの理解が深まる
この記事では、__init__の例を使ってクラスが備えている便利な機能の例を紹介しました。
実際には、__init__だけではなく、非常に多くの機能がクラスには備わっています。
そういった機能を一つずつ理解していくことが、クラスへの理解につながっていきます。
今は、情報を便利に整理するために使われている、といったイメージでも大丈夫です。
クラスのまとめ
(1) クラスは関数と同じようなイメージ。
(2) クラスを実行することを、オブジェクトを作成すると言う。
(3) クラスはオブジェクトを作成した時に実行される便利な関数がある。
(4) クラスを使うことで、複雑なデータをすっきりと整理することができる。
クラスを学んだ後は
クラスと密接な関係にあるオブジェクトについて学んでいきましょう。