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

Web APP Python
スポンサーリンク

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

7日目のテーマは
「while と終了条件を“機能ごとに増やしても、破綻しない形でまとめきる”こと」です。

ここまでであなたは、

  • 単純な繰り返し入力
  • 空文字・重複・最大件数・最大回数
  • メニュー構造(外側 while と内側 while)
  • エラー時のやり直しと終了条件の分離

まで来ています。

7日目では、仕上げとして

  • 「検索」機能
  • 「削除」機能

を追加しつつ、

  • while を増やしても、終了条件が迷子にならない書き方
  • 「どの while が、どこまでを担当しているか」を意識した設計

を確認していきます。


全体像:機能が増えても「外側の while」は変えない

まずはメニューを拡張したイメージ

今日のメニューは、こういう感じにします。

1: メモを追加する
2: メモ一覧を見る
3: メモを検索する
4: メモを削除する
5: 終了する

ここで大事なのは、

「メニューの選択肢が増えても、外側の while の“役割”は変えない」

ということです。

外側の while の責任は、あくまで

「ユーザーに次にやりたいことを選んでもらう」
「終了を選んだらアプリ全体を終わらせる」

だけです。


外側の while(アプリ全体)のコード

まずは骨組みだけ書いてみる

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

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

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

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


memos = []
running = True

while running:
    choice = ask_menu_choice()

    if choice == "1":
        add_memos(memos, max_memos=20)
    elif choice == "2":
        show_memos(memos)
    elif choice == "3":
        search_memos(memos)
    elif choice == "4":
        delete_memo(memos)
    elif choice == "5":
        print("アプリを終了します")
        running = False
Python

ここでの終了条件は、たったひとつです。

choice が “5” のとき、running = False にして外側の while を終わらせる。

それ以外は「どの機能を呼ぶか」を決めているだけ。
外側の while に、余計な終了条件を増やさないのがポイントです。


メモ追加機能の while と終了条件の整理

add_memos の役割を言葉で決める

add_memos の責任は、

「メモ追加モードの中で、繰り返し入力を管理する」
「このモードをいつ終わるかを決める」

です。アプリ全体を終わらせる責任はありません。

コードと終了条件

def add_memos(memos, max_memos=20):
    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)} 件 / 最大 {max_memos} 件)")
Python

この while の終了条件は、はっきり 2 種類です。

ユーザー終了条件:終了 / end と入力されたら break。
アプリ終了条件:最大件数に達したら break。

それ以外は「やり直し条件」(continue)です。

ここで意識してほしいのは、

「この while は“メモ追加モードの中だけ”を担当している」

ということ。
アプリ全体の終了は、外側の while に任せています。


メモ一覧表示は「while を持たない」機能

show_memos の責任は“表示だけ”

一覧表示は、繰り返し入力ではないので while は不要です。

def show_memos(memos):
    print("==== メモ一覧 ====")
    if not memos:
        print("まだメモがありません")
        return

    for i, memo in enumerate(memos, start=1):
        print(f"{i}: {memo}")

ここには終了条件はありません。
「やることを一回やって終わる」だけの関数です。

こういう“単発処理”と、
“繰り返し処理(while が必要なもの)”を
頭の中で分けておくと、設計が楽になります。


検索機能の while と終了条件

search_memos の仕様を日本語で決める

検索機能のルールを先に言葉にします。

検索キーワードを入力してもらう。
空文字なら「検索をやめる」。
キーワードを含むメモだけを表示する。
検索が終わったら、メニューに戻る。

ここでは「繰り返し検索するかどうか」をどうするか、選べます。

今回はシンプルに「1 回検索したら終わり」にします。

コードと終了条件

def search_memos(memos):
    if not memos:
        print("検索できるメモがまだありません")
        return

    keyword = input("検索キーワードを入力してください(空 Enter でキャンセル):").strip()

    if keyword == "":
        print("検索をキャンセルしました")
        return

    print(f"「{keyword}」を含むメモを検索します")

    hits = []
    for i, memo in enumerate(memos, start=1):
        if keyword in memo:
            hits.append((i, memo))

    if not hits:
        print("該当するメモはありませんでした")
        return

    print("=== 検索結果 ===")
    for index, memo in hits:
        print(f"{index}: {memo}")
Python

ここには while はありません。
終了条件はすべて「return」で表現されています。

メモがない → すぐ return。
キーワードが空 → すぐ return。
ヒットがない → 結果を出して return。

この関数の責任は
「1 回の検索を完了させること」だけなので、
while は不要、終了条件は return で十分です。


削除機能の while と終了条件

delete_memo の仕様を日本語で整理する

削除は、少しだけ複雑です。

メモ一覧を番号付きで表示する。
削除したい番号を入力してもらう。
空 Enter なら削除モードをやめる。
数字でない入力や範囲外の番号なら、やり直してもらう。
正しい番号なら、そのメモを削除して、削除結果を表示する。

ここでは「削除モードの中で、番号入力を繰り返す」ために while を使います。

コードと終了条件

def delete_memo(memos):
    if not memos:
        print("削除できるメモがまだありません")
        return

    while True:
        print("==== メモ一覧(削除用) ====")
        for i, memo in enumerate(memos, start=1):
            print(f"{i}: {memo}")

        raw = input("削除したい番号を入力してください(空 Enter で削除モード終了):").strip()

        if raw == "":
            print("削除モードを終了します")
            break

        if not raw.isdigit():
            print("数字を入力してください")
            continue

        index = int(raw)

        if not (1 <= index <= len(memos)):
            print(f"1〜{len(memos)} の範囲で入力してください")
            continue

        deleted = memos.pop(index - 1)
        print(f"削除しました: {deleted}")

        if not memos:
            print("すべてのメモが削除されました。削除モードを終了します。")
            break
Python

この while の終了条件を整理すると、こうなります。

ユーザー終了条件:空 Enter で break。
アプリ終了条件:メモが 0 件になったら break。

やり直し条件:数字でない、範囲外の番号 → continue。

ここでも、

「この while は“削除モードの中だけ”を担当している」

という意識が大事です。

アプリ全体の終了は、やはり外側の while の責任です。


7日目で一番大事な視点:while と終了条件の“責任範囲”

ここまでのコードを、責任範囲で整理してみます。

外側の while(アプリ全体)
アプリを続けるか、終わるかだけを決める。
終了条件は「メニューで終了が選ばれたとき」だけ。

add_memos の while(メモ追加モード)
メモ追加の繰り返しを管理する。
終了条件は「終了コマンド」か「最大件数」。

delete_memo の while(削除モード)
削除対象番号の入力を繰り返す。
終了条件は「空 Enter」か「メモが空になったとき」。

ask_menu_choice の while(メニュー入力)
正しいメニュー番号が入力されるまで繰り返す。
終了条件は「1〜5 のどれかが入力されたとき」。

search_memos / show_memos
単発処理。while は持たず、必要なところで return。

こうやって見ると、

「どの while が、どこまでを担当しているか」

がはっきり分かれているのが見えると思います。

これが、7日目で一番確認してほしい感覚です。


7日目のまとめ:あなたがもうできていること

ここまで来たあなたは、もう

while を書ける人
ではなく
while と終了条件でアプリの構造を組み立てられる人

になりつつあります。

今日の本質を一言で言うと、

「while と終了条件は“機能ごと・階層ごと”に責任範囲を分けて設計する」

です。

1つの巨大な while に全部詰め込むのではなく、

外側の while:アプリ全体の流れ
内側の while:モードごとの繰り返し
関数内の return:その機能の終わり

というふうに、
“どこで終わるか”を丁寧に分割してあげる。

ここまで意識できていれば、
この先、GUI アプリでも Web アプリでも、
「ループと終了条件」で迷子になることは、かなり減ります。

もし余力があれば、

検索を「何度も続けられるモード」にする
削除後に「続けるか?」を聞いてみる

など、自分なりに while と終了条件をいじってみてください。
そこから先は、もう「練習」ではなく「設計遊び」です。

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