こんにちは。
最近いろんな人のPythonコードを眺めていると、「なんでこんなに複雑なシステムなのに、クラス使わずに関数で頑張ってるんだろう」と思うことが多々あります。
多分クラスの書き方というか、オブジェクト指向についてよく理解してなかったり、関数で実装するのに精一杯で、先々を見通してコードが書けない人がいるのが原因ではないかと推測しました。
Pythonでクラスが使えないというのは、戦闘機に例えるならメインウェポンを封じられてサブウェポンだけで戦ってるようなものです。
というわけで今回は、一人でも多くの方がクラスでコードが書けるようになってほしいので、クラス作成について解説したいと思います。
それではよろしくお願いします。
なぜクラス(オブジェクト指向)で書いた方がいいのか?
なぜクラスで書いた方が良いかについてですが、端的にいえば「便利だから」です。
どのように便利になるのかというと、
- Pythonのライブラリやフレームワークのようなものが自作でき、それを自由に使える(使用性)
- データや関数同士がまとまっている(密である)ため、どこになにがあるのかを把握しやすくなる(可読性)
- コードのメンテナンスがしやすくなる(効率性)
つまりプログラムとしての品質を総じてあげることができ、開発現場にとっては負担軽減になるため、使わない理由はないといえます。
ちなみに著者の体験でいうと、めちゃくちゃ複雑なシステムなのに、クラスを一つも使わないで、複数の関数を羅列した数千行に及ぶファイルを、複雑なフォルダ構造で組まれた案件に携わったことが何度かあります。
それぞれの機能の意味とか、関数同士のつながりとか、必要なデータを理解・整理するだけで、数週間以上かかったこともあり、開発効率として最低最悪です。
あれはパワハラというかモラハラ以外の何物でもないので、皆様は絶対にやめてください。
そもそもクラスってどう書いたらいいかわからないんだけど
オブジェクト指向で考えるとは?というところから解説します。
オブジェクト指向というのは、端的にまとめると「抽象的な概念の設計図を書くこと」です。
わかりづらいと思うので、「自動車」を例にあげてみます。
皆さん、自動車といえば何を思い出しますか?抽象的にイメージしてみましょう。
まずタイヤが4つあると思います。3輪のもあるよという指摘も良いと思います。
人が乗り込める空間がありますよね。
それからエンジン、いわゆる動力源なので、モーターの場合も最近ではあるでしょう。
あとはメーカーによって名前があり、いろいろ装備や特徴が異なるというのもあるでしょう。
こんな感じで、「自動車という抽象的な概念が持つべき基本的な情報」を属性といいます。
では次に、自動車は何ができるでしょう?
当然「走る」「曲がる」「止まる」ができるのが基本的な機能になると思います。
このように「自動車という抽象的な概念が行える機能」のことをメソッド(関数)といいます。
この属性とメソッドを定義することが、クラスを書く準備段階(設計)として必要になります。
では早速書いてみましょう。
クラスの設計ができたら、あとは書いてみる
では早速書いてみましょう。
先ほど定義した属性に関する情報から書いていきます。
タイヤの数(tire_num)、乗員数(human_num)、メーカー名(maker)とすると、以下のようになります。
class Car:
def __init__(self, tire_num, human_num, maker):
self.tire_num = tire_num
self.human_num = human_num
self.maker = maker
__init__というのは、専門用語では「コンストラクタ」と呼ばれますが、わかりづらいと思うので、「Carというクラスを使う準備をしたときに、必ず最初に行われる初期化処理」と理解してください。
では次は機能となるメソッドを書いていきましょう。
「走る」「曲がる」「止まる」に加えて、車の情報を表示する機能も追加してみます。
class Car:
def __init__(self, tire_num, human_num, maker):
self.tire_num = tire_num
self.human_num = human_num
self.maker = maker
def run(self):
print(f"{self.maker}が走るよ!")
def turn(self):
print(f"{self.maker}がまがるよ!")
def stop(self):
print(f"{self.maker}がとまるよ!")
def info(self):
print(
f"タイヤ数:{self.tire_num}、乗員数:{self.human_num}、メーカー名:{self.maker}"
)
はい、これで車というクラスが完成しました!
selfというのはクラス自身(Car)を指し、属性やメソッドをクラス内であれば自由に呼び出すことができます。
これにより、冒頭で申し上げた「データと関数同士の関連性」がとても密なコードを作成できるようになるのです。
で、どうやってクラスを使えばいいの?
じゃあ早速この車を走らせてみましょう!
続けて以下のように書いてください。
class Car:
def __init__(self, tire_num, human_num, maker):
self.tire_num = tire_num
self.human_num = human_num
self.maker = maker
def run(self):
print(f"{self.maker}が走るよ!")
def turn(self):
print(f"{self.maker}がまがるよ!")
def stop(self):
print(f"{self.maker}がとまるよ!")
def info(self):
print(
f"タイヤ数:{self.tire_num}、乗員数:{self.human_num}、メーカー名:{self.maker}"
)
toyota = Car(4, 5, "Toyota")
toyota.run()
これだけでOKです。
toyotaという車(オブジェクト)がCar(4, 5, “Toyota”)によって具現化するイメージです。
(専門用語的には「インスタンス化」といいます。)
そうするとtoyotaというオブジェクトは、runという機能をもっているので、「.run()」で実行できるというわけです。
実行結果は以下のようになります。
Toyota車が走りましたね!
このように、クラスで実装すると、実際に動かす際はとてもシンプルにコードが書けます。
なので複雑なシステムになればなるほど、クラスで書くことの恩恵はとても大きくなるのです。
そして自動車というクラスを作ったことで、例えば日産の車やホンダの車を作ることも容易であることが想像できるでしょうか?
関数だと、トヨタ用、日産用、本田用・・・と、非常に煩雑なコードになってしまいそうです。
このように、先々の見通しというのも立てやすいため、拡張性の高いメンテナンスしやすいコード管理ができるようになるのがクラス作成のメリットになります。
まとめ
それでは今回のまとめです。
コードの可読性、メンテナンス性など、開発現場の効率を上げると同時にコードの品質もあげられる便利ツールだから。
抽象的な概念の設計図を描くイメージ。
抽象的な概念が持つ基本的な情報:属性
抽象的な概念が持つ基本的な機能:メソッド
属性とメソッドを定義する。
インスタンス化し、インスタンスオブジェクトが持つメソッドを実行するだけ。
というわけで、クラスの作り方について、解説してみました。
Pythonのオブジェクト指向は開発現場もコードもより良いものにしてくれるので、こんな便利なものを使わないのはもったいないです。
最初は難しく感じるかもしれませんが、できるところから、簡単なレベルからでいいのでぜひ練習してみてください。
ここまでご覧いただきありがとうございました。