Class
前回、JSON形式のファイルを使って、設定ファイルの読み込み方を解説しました。
今回はDjangoをやっていて出てきたクラスというものを色々といじっていきます。
ただ試してみて思ったのは、はっきり言ってよく分からない…
例えば今回出てくるものとして、「コンストラクタ」というものがあります。
多くのサイトでこの「コンストラクタ」の使い方を解説しているのですが、これを使うことでなんのメリットがあるのか、これがないと何ができないのか、ということを”初心者がわかるレベル”とか”クラスを初めて使う人が分かるレベル”で解説してくれているサイトには出会えませんでした。
ということでとりあえず正確な意味はおいておいて、自分が納得して使えるレベルになるよういじってみたというのが今回の流れです。
それでは始めていきましょう。
関数
とその前に、クラスに似た書き方をするものとして「関数」があります。
例えばこんな感じ。
def test1(val1, val2):
ans = val1 + val2
return ans
print(test1(1,2))
実行結果
3
同じプログラムを繰り返し簡単に使えるように定義する方法でした。
もう少し詳しく知りたい方は前に関数の記事を書いていますので、よかったらこちらもどうぞ。
まずはこの関数と比較しつつクラスの使い方を勉強していきます。
クラスの書き方
先ほどの関数を基本としてクラスを書いていきます。
class Calc:
def test2(val1, val2):
ans = val1 + val2
return ans
print(Calc.test2(1,2))
実行結果
3
注目すべきは「class Calc:」が増えたこと、そしてdef文のインテンドが一つ増えたこと、さらに呼び出す際に「Calc.test2(1, 2)」というように、コマンドの前に「Calc」が増えたことです。
正直言ってどれも手間がかかることになるだけで、そのメリットがあるように思えません。
ちなみに呼び出す際に「Calc.」を付けないとエラーになります。
print(test2(1,2))
実行結果
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-13-63a9ea551e9a> in <module>
----> 1 print(test2(1,2))
NameError: name 'test2' is not defined
デメリットばかりに見えるクラスですが、どうも中にある関数、クラスの場合には「メソッド」と呼ぶようです、が少ない場合、あまり意味をなさないようです。
ということで増やしてみました。
class Calc:
def test2(val1, val2):
ans = val1 + val2
return ans
def test3(val1, val2):
ans = val1 - val2
return ans
def test4(val1, val2):
ans = val1 * val2
return ans
def test5(val1, val2):
ans = val1 / val2
return ans
print(Calc.test2(1,2))
print(Calc.test3(1,2))
print(Calc.test4(1,2))
print(Calc.test5(1,2))
実行結果
3
-1
2
0.5
こう書くとちょっとクラスのメリットが見えてきました。
同じようなメソッドをまとめておくことで、分かりやすく呼び出せると感じます。
例えば上の例では四則演算をメソッドに入れてあり、それをまとめて「Calc」というクラスで呼び出せるようにしたことから、プログラムの分かりやすさが向上します。
インスタンス変数
次はインスタンス変数です。
こちらも言葉の意味はよく分かりませんが、Classのすぐ下にある変数のようです。
ということでこんな感じ。
class Calc:
val0 = 10
def test2(val1, val2):
ans = val1 + val2 + val0
return ans
def test3(val1, val2):
ans = val1 - val2 - val0
return ans
def test4(val1, val2):
ans = val1 * val2 * val0
return ans
def test5(val1, val2):
ans = val1 / val2 / val0
return ans
print(Calc.test2(1,2))
print(Calc.test3(1,2))
print(Calc.test4(1,2))
print(Calc.test5(1,2))
実行結果
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-7-aee8aafbf3f7> in <module>
15 return ans
16
---> 17 print(Calc.test2(1,2))
18 print(Calc.test3(1,2))
19 print(Calc.test4(1,2))
<ipython-input-7-aee8aafbf3f7> in test2(val1, val2)
3
4 def test2(val1, val2):
----> 5 ans = val1 + val2 + val0
6 return ans
7 def test3(val1, val2):
NameError: name 'val0' is not defined
単純に定義すればいいと思ったら、それではエラーがでてしまいます。
どうするかというとこうします。
class Calc:
val0 = 10
def test2(self, val1, val2):
ans = val1 + val2 + self.val0
return ans
def test3(self, val1, val2):
ans = val1 - val2 - self.val0
return ans
def test4(self, val1, val2):
ans = val1 * val2 * self.val0
return ans
def test5(self, val1, val2):
ans = val1 / val2 / self.val0
return ans
calculation = Calc()
print(calculation.test2(1,2))
print(calculation.test3(1,2))
print(calculation.test4(1,2))
print(calculation.test5(1,2))
実行結果
13
-11
20
0.05
変更点は例えば「def test2(self, val1, val2):」のように第一引数に「self」を入れている点。
そして「calculation = Calc()」という行が追加されている点。
さらに「print(calculation.test2(1,2))」というように「calculation = Calc()」の変数でメソッドを呼び出している点です。
selfというのはどうやらClassの直下に書かれた変数を呼び出すための引数。
そしてそれは「calculation = Calc()」というように一度クラスを呼び出してやることによって実行される。
そのためメソッドを呼び出すときに「calculation = Calc()」の変数名を使って「print(calculation.test2(1,2))」というように呼び出す必要があるようです。
コンストラクタ
また分からない言葉が出てきました。
コンストラクタとはインスタンス実行時に呼び出される特別なメソッドとのことらしいのですが、全く分かりません。
とりあえず試してみましょう。
class Calc:
def __init__(self):
self.val0 = 10
def test2(self, val1, val2):
ans = val1 + val2 + self.val0
return ans
def test3(self, val1, val2):
ans = val1 - val2 - self.val0
return ans
def test4(self, val1, val2):
ans = val1 * val2 * self.val0
return ans
def test5(self, val1, val2):
ans = val1 / val2 / self.val0
return ans
calculation = Calc()
print(calculation.test2(1,2))
print(calculation.test3(1,2))
print(calculation.test4(1,2))
print(calculation.test5(1,2))
実行結果
13
-11
20
0.05
先ほどと大きく変わらないように見えますが、変わった点といえば、最初に「def __init__(self):」という1行が増え、その中の変数に「self」が付いただけのように見えます。
でも実はこの「def __init__(self):」がコンストラクタなのです。
そしてこのコンストラクタは「calculation = Calc()」とされたときに実行されます。
ただこのままではその良さが分かりません。
ということでこうしてみました。
class Calc:
def __init__(self, val):
self.val0 = val
def test2(self, val1, val2):
ans = val1 + val2 + self.val0
return ans
def test3(self, val1, val2):
ans = val1 - val2 - self.val0
return ans
def test4(self, val1, val2):
ans = val1 * val2 * self.val0
return ans
def test5(self, val1, val2):
ans = val1 / val2 / self.val0
return ans
calculation = Calc(100)
print(calculation.test2(1,2))
print(calculation.test3(1,2))
print(calculation.test4(1,2))
print(calculation.test5(1,2))
実行結果
103
-101
200
0.005
変わった点は「def __init__(self, val):」、その中の変数「self.val0 = val」、そして「calculation = Calc(100)」。
つまりクラスを呼び出すときに引数を設定することで、それをクラス全体の変数として使えるというわけです。
とまぁクラスの説明をしてきましたが、正直合っているのか、自分自身がよく分かっていなかったりします。
ただ重要なことは「使える」ということだと思いますし、これくらいのことを理解しておけば十分クラスを使っていけるのではないかと思います。
次回はWebアプリ作成に戻って、今度はBootstrapというWebデザインのフレームワークを使ってみましょう。
ではでは今回はこんな感じで。
コメント