前ページ(2-7:関数) | 目次へ戻る | 次ページ(2-9:ファイル分け)
複雑なものを作っていくとその分ソースコードが長くなるので関数に分けることを説明しました。
ですが、その関数も数が多くなってきたりするとそれもまた管理やメンテナンスが大変になってきます。
また機能として似たようなもの、例えば「生徒の合計点を計算する関数」と「生徒の平均点を計算する関数」は用途としては「生徒に関する関数」なので、まとめておきたいです。
そこで関数を集めたものである「クラス」を作成する必要が出てきます。
Pythonでのクラスの書き方は以下のようになります。
class [クラス名]:
[クラス定数]
def __init__(self): # def __init__(self, a, b):のように引数設定も可能
[コンストラクタの処理]
self.[クラス変数名]
def [関数名1](self):
[関数の処理1]
def [関数名2](self, a, b):
[関数の処理2]
classのところでクラス名を設定します。一般的にクラス名の一文字目は大文字を使います。
クラス名の後には、そのクラスが持つ「定数(変わらない値)」を記述します。一般的に全て大文字の定数名にします。クラス定数は次に説明するコンストラクタが呼ばれなくても「クラス名.クラス定数」で取得することができます。
「def __init__(self):」とありますが、これは「コンストラクタ」と呼ばれます。
コンストラクタはクラスを作成する際に一番最初に呼ばれる関数で、基本的に変数の初期化処理やクラスを扱う際に必ず必要になる引数をクラス変数に設定する処理を記述します。
コンストラクタの引数にある「self」ですが、これは「オブジェクト(作成されたクラス自身)」を表しています。
あとはクラスに持っておきたい関数と処理をどんどん書いていくだけです。
コンストラクタを記述した場合やクラス変数を使う必要がある場合は必ずこの「self」を引数の最初に書くようにします。
書き方がわかったので実際に具体的なクラスを書いてみます。
以下が「SumClass」という足し算を行うクラスを作成し、そのクラスのオブジェクトを作成しています。
・2-08_01_class_test.py
# 「SumClass」というクラスを作成
class SumClass:
# クラス定数
CONST_NUMBER = 1000
# コンストラクタ
def __init__(self):
# コンストラクタはクラスオブジェクトが作成されるときに呼ばれる
self.add1 = 0
self.add2 = 0
print("constructor called")
def set_number(self, a, b):
# クラス変数に値を代入
self.add1 = a
self.add2 = b
def calc_sum(self):
# 計算結果を返す
return self.add1 + self.add2
def show_set_number(self):
# 設定されているクラス変数の値を表示
print("add1: ", self.add1)
print("add2: ", self.add2)
def calc_and_show(self):
# クラス内の他関数も以下のように呼び出すことができる
result = self.calc_sum()
print(result)
def show_const_number(self):
# クラス定数もクラス内関数と同様に以下のように呼び出すことが可能
print(self.CONST_NUMBER)
print(SumClass.CONST_NUMBER) # クラス定数の表示
# SumClassという「オブジェクト」をsc1として作成(ここでコンストラクタが呼ばれる)
sc1 = SumClass()
sc1.set_number(5, 8) # 足したい数を設定
sc1.show_set_number() # クラス変数に設定された値を確認
# SumClassという「オブジェクト」をsc2として作成(ここでコンストラクタが呼ばれる)
sc2 = SumClass()
sc2.set_number(21, 907) # 足したい数を設定
sc2.show_set_number() # クラス変数に設定された値を確認
print(sc1.calc_sum()) # sc1の足し算の結果を表示
print(sc2.calc_sum()) # sc2の足し算の結果を表示
# ちなみにクラス変数は以下の形で直接アクセスできるが、書き換えたりできるのであまり推奨されない
print(sc2.add1)
sc2.add1 = 50000 # 書き換え
print(sc2.add1)
クラスという概念を理解するのはすんなりいかないと思うので、色々と関数をまとめたクラスを書いて慣れていってください。
最初の方にも少し書きましたが、クラスは関数をまとめたものです。
クラスを書くことでデータや関数を一つのオブジェクトとして扱えるので、とても便利です。
またクラスの書き方で書いたソースコード例にあるように、SumClassのオブジェクトを複数作成することで、中身のソースコードは同じでも与えるデータを変更することで違った結果を持つことも可能になります。
このように管理やメンテナンスをしやすくするだけでなく、同じソースコードでも違う結果を持つことができるという利点があります。
クラスも関数と同様に人によって分け方が違ってきますが、ここでもまたプログラマーのセンスが問われます。
詳しくは解説しませんが「オブジェクト指向」という考え方がちょっと前までは流行っていましたが、今は何が流行っているのか自分は把握しきれていません。
ただオブジェクト指向という言葉も割とふわっとしているので、ちゃんと調べて理解しようとするとなかなか難しいです。(自分自身もちゃんと理解できているかと言われると微妙なところです)
ではどうすればよいのかですが、基本的なクラス分けの考え方としては「どうクラス分けすれば処理やデータの持ち回りが楽になり、またメンテナンスもしやすくなるか?」と考えて適切に分けることが一番重要なので、流行りが言葉に惑わされずにもっとも効率が良くなりそうな形でクラス分けをするようにしましょう。
また考え方として「結合度は低く、凝集度は高く」というものがあるので、気になる方は各自で「結合度 凝集度」などで検索して調べてみてください。
生徒の名前と各教科の点数を保持し各教科の合計点と平均点を計算するStudentクラスを作成して、それぞれの生徒の合計点と平均点を表示させてみてください。
| 生徒名 | 国語 | 英語 | 数学 |
|---|---|---|---|
| Sato | 63 | 42 | 78 |
| Sasaki | 33 | 98 | 42 |
| Miura | 13 | 62 | 89 |
# Studentクラス
class Student:
SUBJECT_NUM = 3 # 教科数
# コンストラクタ
def __init__(self, name, language, english, math):
# 名前と点数を引数として各値をクラス変数に設定
self.name = name
self.language = language
self.english = english
self.math = math
# 合計点を計算
def calc_sum(self):
return self.language + self.english + self.math
# 平均点を計算
def calc_average(self):
return self.calc_sum() / self.SUBJECT_NUM
# 名前と合計、平均を表示(今回はまとめているがまとめなくてもよい)
def show_data(self):
sum_point = self.calc_sum()
average_point = self.calc_average()
message = "[" + self.name + "] sum: "
message = message + str(sum_point) + " average: "
message = message + str(average_point)
print(message)
# 各生徒のオブジェクトを作成
sato = Student("Sato", 63, 42, 78)
sasaki = Student("Sasaki", 33, 98, 42)
miura = Student("Miura", 13, 62, 89)
# 各オブジェクト毎の名前、合計、平均を計算して表示
sato.show_data()
sasaki.show_data()
miura.show_data()