Python | 1 日 90 分 × 7 日アプリ学習:繰り返し入力メモアプリ(初級編)

Web APP Python
スポンサーリンク

6日目のゴールと今日やること

6日目のテーマは
「while と終了条件を“エラー処理”と組み合わせて、壊れにくい入力ループにすること」です。

ここまでであなたは、

  • 終了コマンドで終わる
  • 最大件数・最大回数で終わる
  • メニュー構造で外側・内側の while を分ける

ところまで来ています。

今日はそこに、

  • 「数字を入力してほしいのに、文字が来た」
  • 「存在しないメニュー番号が入力された」

といった“よくある入力ミス”を、
while と終了条件の設計でどう扱うか、をやっていきます。


メニュー入力の「よくある事故」を言葉にしてみる

どんなミスが起きるかを先に想像する

メニュー付きアプリで、よくあるパターンはこうです。

  • 1〜3 の数字を期待しているのに、「a」や「0」や「10」が来る
  • 空文字(Enter だけ)が来る
  • 半角スペースだけが来る

これを全部「終了条件」にしてしまうと、
アプリがすぐ終わってしまって使いづらいですよね。

なので今日は、

  • 「アプリを終わらせる条件」
  • 「この入力だけやり直してもらう条件」

を、さらに丁寧に分けていきます。


メニュー入力を「while で再入力させる」発想

外側の while の中に、もう一段“小さな while” を作る

まずは、メニュー部分だけに注目します。

やりたいことはこうです。

  • メニュー番号が正しく入力されるまで、メニュー入力を繰り返す
  • ただし、アプリ全体の終了は「3」を選んだときだけ

これをコードにすると、こうなります。

def ask_menu_choice():
    while True:
        print("==== メニュー ====")
        print("1: メモを追加する")
        print("2: メモ一覧を見る")
        print("3: 終了する")

        choice = input("番号を入力してください:").strip()

        if choice in ("1", "2", "3"):
            return choice

        print("不正な入力です。1〜3 の番号を入力してください。")


memos = []
running = True

while running:
    choice = ask_menu_choice()

    if choice == "1":
        print("メモ追加モードに入ります(あとで実装)")
    elif choice == "2":
        print("メモ一覧を表示します(あとで実装)")
    elif choice == "3":
        print("アプリを終了します")
        running = False
Python

ここでのポイントは、

  • メニュー入力専用の while を ask_menu_choice に閉じ込めた
  • 外側の while は「正しい choice が返ってくる前提」で動ける

という構造になっていることです。


深掘り:終了条件を「関数の責任」として考える

ask_menu_choice の終了条件は何か?

ask_menu_choice の中だけを見て、
終了条件を言葉にしてみます。

  • choice が “1” / “2” / “3” のどれかになったら、return して while を抜ける
  • それ以外なら、エラーメッセージを出して while を続ける

つまり、この関数の終了条件は
「正しいメニュー番号が入力されたとき」です。

ここが大事で、

この関数は「アプリを終わらせるかどうか」は決めていない

ということです。

アプリを終わらせるかどうかは、
外側の while(running を管理している側)の責任です。

終了条件を「どのレイヤーの責任か」で分ける、
という感覚が出てきています。


メモ追加モードにも「入力ミスの while」を入れる

文字数制限や「やめたくなったとき」の扱い

次に、メモ追加モードを少しだけ強化します。

仕様を日本語で書くとこうです。

  • メモは 1〜50 文字にしたい
  • それを超えたら「長すぎます」と言って再入力させる
  • ただし「終了」/「end」と入力されたら、モード自体を終わる

これをコードにすると、こうなります。

def add_memos(memos, max_memos=5):
    print("メモ追加モードです。終了 / end でメモ追加を終わります。")
    print(f"現在 {len(memos)} 件 / 最大 {max_memos} 件")

    while True:
        raw = input("メモを入力してください:")
        text = raw.strip()
        normalized = text.lower()

        if normalized in ("終了", "end"):
            print("メモ追加モードを終了します")
            break

        if text == "":
            print("空のメモは保存しません")
            continue

        if len(text) > 50:
            print("50文字を超えています。もう少し短くしてください。")
            continue

        if text in memos:
            print("同じメモがすでに登録されています")
            continue

        if len(memos) >= max_memos:
            print("メモの最大件数に達しました。これ以上追加できません。")
            break

        memos.append(text)
        print(f"追加しました(現在 {len(memos)} 件)")
Python

ここでも、終了条件と「やり直し条件」を分けています。

  • 終了条件(モードを終わる):終了 / end、最大件数
  • やり直し条件(この入力だけ無効):空文字、長すぎる、重複

どれも while の中にありますが、
役割が違うことを意識して書いています。


「エラー処理」と「終了条件」の境界線をはっきりさせる

どこまで行ったら“終わり”にするのか

6日目で一番深く考えてほしいのは、ここです。

  • 入力が変でも「やり直してもらえばいいだけ」のケース
  • 入力がこうなったら「このモード自体を終わらせる」ケース

この境界線を、自分で決められるようになること。

例えば、メニュー入力で
「3 以外は全部エラーにして再入力」
と決めることもできます。

逆に、

「q と入力されたら、メニュー入力自体をやめてアプリ終了」

というルールを足すこともできます。

大事なのは、

「この状況は“終わり”なのか、“やり直し”なのか?」

を、毎回自分に問いかけてから
終了条件を書くことです。


外側と内側、エラーと終了を合わせた全体像

ここまでの要素をまとめた形

少し長くなりますが、
6日目までの考え方を全部入れた“雰囲気コード”を載せます。

def ask_menu_choice():
    while True:
        print("==== メニュー ====")
        print("1: メモを追加する")
        print("2: メモ一覧を見る")
        print("3: 終了する")

        choice = input("番号を入力してください:").strip()

        if choice in ("1", "2", "3"):
            return choice

        print("不正な入力です。1〜3 の番号を入力してください。")


def add_memos(memos, max_memos=5):
    print("メモ追加モードです。終了 / end でメモ追加を終わります。")
    print(f"現在 {len(memos)} 件 / 最大 {max_memos} 件")

    while True:
        raw = input("メモを入力してください:")
        text = raw.strip()
        normalized = text.lower()

        if normalized in ("終了", "end"):
            print("メモ追加モードを終了します")
            break

        if text == "":
            print("空のメモは保存しません")
            continue

        if len(text) > 50:
            print("50文字を超えています。もう少し短くしてください。")
            continue

        if text in memos:
            print("同じメモがすでに登録されています")
            continue

        if len(memos) >= max_memos:
            print("メモの最大件数に達しました。これ以上追加できません。")
            break

        memos.append(text)
        print(f"追加しました(現在 {len(memos)} 件)")


memos = []
running = True

while running:
    choice = ask_menu_choice()

    if choice == "1":
        add_memos(memos, max_memos=5)
    elif choice == "2":
        print("==== メモ一覧 ====")
        if not memos:
            print("まだメモがありません")
        else:
            for i, memo in enumerate(memos, start=1):
                print(f"{i}: {memo}")
    elif choice == "3":
        print("アプリを終了します")
        running = False
Python

ここには、いろんなレベルの終了条件が混ざっています。

  • アプリ全体の終了条件:choice == “3”
  • メニュー入力の終了条件:正しい番号が入力されたら return
  • メモ追加モードの終了条件:終了 / end、最大件数

そして、

  • メニュー入力のエラー → 再入力
  • メモ入力のエラー → 再入力

という「やり直しの while」も入っています。


今日いちばん深く理解してほしいこと

6日目の本質は、

「終了条件」と「エラー時のやり直し」を、意識的に分けて設計することです。

  • 終わらせるのか
  • もう一度やってもらうのか

この二択を、毎回ちゃんと自分で決める。

そして、その決定を

  • break(モードを終わる)
  • return(関数を終わる)
  • continue(この1回だけスキップして続ける)

としてコードに落とし込む。

ここまで来ると、
while と終了条件はもう「文法」ではなく、
アプリの体験をデザインする道具になっています。

7日目は、このメモアプリに
「削除」「検索」などの機能を足しながら、
同じ考え方で終了条件とループを組み立てていく、
というところまで持っていきましょう。

タイトルとURLをコピーしました