Python学習チャンネル by PyQ

Pythonのオンライン学習プラットフォームPyQのオフィシャルブログです

Pythonの実装で、辞書のキーをタイポ(typo)していました。タイポに気づきやすくする方法はありますか?

f:id:kenken0326:20201013152947p:plain

PyQチームのtsutomuです。

今回は、PyQのお問い合わせにあった問題の解決方法を考えてみます。

質問

コンピューターとじゃんけんをするWebアプリケーションを作成したいのですが、コンピューターの手が表示されません。どうすれば表示されるようになりますか?

書いたコード

res = {"computer": "", "user": "", "result": ""}
res["conputer"] = random.randint(0, 2)

回答

この問題の原因は辞書のキーのタイポ(typo/タイプミス)です。

辞書は任意のキーを使ってもエラーにならない

上記の 「書いたコード」のように初期化したあとで、"computer""conputer"とタイポしています。

画面表示では、res["computer"]を参照しているので初期値(空文字列)のため何も表示されていませんでした。

このように辞書は任意のキーを使ってもエラーになりません。このためキーをタイポしても気づきにくくなります。

解決方法

色々な解決方法がありますが、辞書の代わりにクラスを使うのも1つの方法です。クラスのオブジェクトであれば、存在しないデータメンバーを参照するとエラーになるので早めに気づけます。

ここでは、辞書の代わりにクラスDataを使うことにしましょう。
resの要素は3つありましたので、クラスのデータメンバーも同じものを用意しましょう。
また、__init__で勝負の判定もしてしまいましょう。

クラスは下記のようになります。処理をData.__init__に移したことで見通しがよくなりました。

また、__slots__で、データメンバーとして、user, computer, resultだけにしています。クラスの__slots__クラス変数に指定すると、指定したデータメンバーだけ利用できるようになります。
このため、タイポしてもエラーとなるので、すぐわかるようになっています。

class Data:
    __slots__ = ['user', 'computer', 'result']

    def __init__(self, user=-1, computer=-1):
        self.user = user
        self.computer = computer
        if user == computer:
            self.result = "あいこ" if user >= 0 else ""
        else:
            win = (user, computer) in ((0, 1), (1, 2), (2, 0))
            self.result = "勝ち" if win else "負け"

  1. 初期化時は res = Data() とします。
  2. 判定時は、res = Data(user, computer) とします。
  3. templates/index.html は模範解答のままで構いません。

※ 模範解答では、辞書の値をstrで初期化しintで更新していました。上記ではintに統一しています。

__slots__については公式ドキュメントにも書かれています。

docs.python.org

修正後の結果

f:id:kenken0326:20200918102837p:plain

このお悩み解決に関連するクエスト

このお悩み解決はPyQの補足情報として作成しています。PyQユーザーで興味がある方は「68-3: じゃんけんアプリを作ろう」をぜひ解いてみてください。

Copyright ©2017- BeProud Inc. All rights reserved.