【Python】__init__って何かのおまじないですか?【簡単なゲームを作る2】

ケンケン
前回はサブクラスの作り方を学んだね
ミケ
はーい!
ケンケン
今回は、サブクラスをどのタイミングで実行するか決めるプログラムを書いていくよ
ミケ
どうするんですか?
ケンケン
まずは__init__()メソッドを使うんだ
ミケ
何かのおまじないですか?
ケンケン
まぁ最初はおまじないって感じで覚えといてOKだよ(^_^;)それではいってみよう!

 

前回の復習

動物達と交渉して仲間にする簡単なゲームを作っています。

前回は、スーパークラスとサブクラスを作って中身を書き換えるオーバーライドについて勉強しました。

前回復習記事

ケンケン クラスって引き継ぐことができるって知ってる?   コタロウ 知らないです。クラスを引き継ぐといいことあるの? ケンケン 引き継いだ元のクラスのメソッドを書き換えて使ったり、プログラ[…]

 

コードをすっきり書くことが可能になるので、しっかり理解しておきましょう。

 

▶前回書いたコード(Friend.py)

class Friend:
    def friend(self, point):
        return ''

class GoodFriend(Friend):
    def friend(self, point):
        return['動物はよろこんでいる!', point]

class DrawFriend(Friend):
    def friend(self, point):
        point = 0
        return['動物は考えている', point]

class BadFriend(Friend):
    def friend(self, point):
        return['動物は怒っている', -point]

class BestFriend(Friend):
    def friend(self, point):
        point = 20
        return['動物は心打たれた', point]
    
#====================================================
# 実行
#====================================================
if __name__ == '__main__':

    point = 2#とりあえず仮の数値を入力
    partner = GoodFriend()
    res = partner.friend(point)
    print(res)

    partner = DrawFriend()
    res = partner.friend(point)
    print(res)

    partner = BadFriend()
    res = partner.friend(point)
    print(res)

    partner = BestFriend()
    res = partner.friend(point)
    print(res)

 

Controllerクラスを作成しよう

前回スーパークラスとサブクラスを作成しました。

しかし、このままだとサブクラスを作った意味がありません。

それぞれのサブクラスのメソッドを任意で呼び出せる仕掛けが必要になります。

 

今回は、Controllerクラスを作ってそこにサブクラスを呼び出すメソッドを作成します。

 

コードを書こう

まずは、Controllerクラスを定義するコードを書きましょう。

▶Controllerクラスを定義する(Controller.py)

from friend import *#①
import random#②

class Controller:#③
    def __init__(self):
        self.good = GoodFriend()
        self.draw = DrawFriend()
        self.bad = BadFriend()
        self.best = BestFriend()

コードの解説

①「from friend import *」で前回作ったfriendクラスをインポートしています。

ControllerクラスではFriendモジュールを使うことが前提なのであらかじめインポートしておきます。

先頭にfromをつけることによってクラスをまとめて読み込むことができます。

これによりモジュール名friendを記述する必要がなくなり多少便利になります。

 

②randomモジュールをインポートしています。

以降の仕掛けを作る際に必要になります。

 

③以下でいよいよControllerクラスを定義しています。

__init__()メソッドでオブジェクトを初期化しよう

__init__()ですが、何やらあやしい感じがしますね。

initがアンダースコアに囲まれて意味不明ですが、これはinitializeの略です。

 

僕のVBAの記事をご覧いただいた方にはおなじみかもしれませんが、

簡単に言うとプログラムが実行されると同時に呼び出される特殊なメソッドのことです。

初期化のことです。

VBAに興味がある方はご覧ください

みなさん、こんにちはケンケンです。   今回は、ユーザーフォームのリストボックスをご紹介します。 リストボックスはフォーム上にデータリストを表示したり選択することが出来ます。   資料は以前[…]

では、何を初期化すれば良いでしょうか。

今回は、Friendクラスの4つのサブクラスをインスタンス化して

以降のコードで処理できるように初期化しています。

 

インスタンス化について詳しく学習されたい方は以下の記事をご覧ください。

インスタンス化とは?

ケンケン みんなはクラスって知ってる? コタロウ 知ってます!僕らはケンケンクラスのメンバーです! ぺんぺん そうだね! ケンケン そのクラスとは違うんだな。。。 […]

 

negotiationメソッドを作ろう

ゲームらしさをとりいれるために、冒頭でインポートした

randomモジュールを使ってnegotiationメソッドを作ります。

 

ランダムに生成した数字によって呼び出すメソッドを分けて実行します。

具体的にコードを書いてみましょう。

▶negotiationメソッド(Controller.py)

    def negotiation(self, point):
        x = random.randint(0, 100)
        if x <= 30:
            self.friend = self.good
        elif 31 <= x <= 60:
            self.friend = self.draw
        elif 61 <= x <= 90:
            self.friend = self.bad
        else:
            self.friend = self.best
        return self.friend.friend(point)

まずは、randomモジュールのrandintメソッドを使って1から100までの数値をランダムで生成します。

 

1から30までの値でGoodFriendクラスのインスタンスを、

31から60までの値でDrawFriendクラスのインスタンスを、

61から90までの値でBadFriendクラスのインスタンスを、

上記以外の値でBestFriendクラスのインスタンスを、self.friendに代入します。

 

return部分でfriendメソッドの実行時戻り値をnegotiationメソッドの戻り値として返します。

サブクラスを呼び分ける

ちょっと何言ってるかよく分からないかもしれません。

具体的に、ランダムに生成された数字が50だった場合のプログラムの実行手順を一緒になぞってみましょう。

以上のような流れになります。

数字を変えて確認してみてください。そうするとひとつ気づくはずです。

それは、negotiationメソッドでどの数字、つまりどのIf条件式に到達しようとも、

それ以降に使うインスタンス名とメソッド名が同じであることに。

 

これが、オーバーライドしてメソッドを作成するメリットです。

このように同じ名前で呼び出してメソッドを使うことを、ポリモーフィズムと呼んだりします。

参考までに覚えておきましょう。

 

実行部分を作ろう

前回と同様にこのモジュール内のみで実行できるプログラムを記述して、テストできるようにしておきましょう。

テストコードを含めController.pyに記述したすべてのコードを以下にまとめます。

▶全部コード(Controller.py)

from friend import *
import random

class Controller:
    def __init__(self):
        self.good = GoodFriend()
        self.draw = DrawFriend()
        self.bad = BadFriend()
        self.best = BestFriend()

    def negotiation(self, point):
        x = random.randint(0, 100)
        if x <= 30:
            self.friend = self.good
        elif 31 <= x <= 60:
            self.friend = self.draw
        elif 61 <= x <= 90:
            self.friend = self.bad
        else:
            self.friend = self.best
        return self.friend.friend(point)

#=======================================================
# 実行
#=======================================================
if __name__ == '__main__':

    point = 2
    cont = Controller()
    res = cont.negotiation(point)
    print(res)

コードの内容はpointに仮の数値2を代入しておき、Controllerクラスをインスタンス化し、

negotiationメソッドを実行し表示しています。

if __name__ == ‘__main__’:に関しては前回の記事を参考にしてください。

さあ、これを実行してコードに問題がないことを確認しておきましょう。

まとめ

いかがでしたか?

__init__を使うことでオブジェクト生成と同時に初期化することを勉強しました。

クラスやインスタンスなど概念的な知識が増えてきて覚えるのが大変かもですが、

何度もの繰り返してコードを書いていけば理解できるはずなので焦らず学んでいきましょう。

 

次回は実際に動物達と交渉するための実行コードを書いていきますのでお楽しみに!

それではまた次回お会いしましょう。


ケンケン
__init__を使った初期化は理解できたかな?
ミケ
あらかじめ実行したいコードをまとめておけばいいんだね!
ケンケン
そうだね
ケロ
__init__のおまじないで僕の人生も初期化しました!!
ミケ
へぇ、何か変わった?
ケロ
何も変化ありません!!
ミケ
中身のない人生(笑)