🛒

Pythonで買い物メモアプリを作ろう!

に公開

🦘 【プログラミング初心者向け】Streamlit で作る食材買い物メモ

プログラミングで実用的なアプリを作ってみたいけれど、何から始めればいいかわからない...そんな方に朗報です!今回は、Python の Streamlit を使って、オーストラリアの美味しい食材を管理する買い物メモアプリを作成します。

リスト管理、ランダム選択、セッション状態の管理まで含む本格的なアプリを、初心者でも理解できるように詳しく解説していきます。

🌟 この記事を読めば...

リスト操作とデータ管理の使い方を楽しく学べます 🎯

この記事では、単なる買い物メモアプリを作るだけでなく、プログラミングの基本であるリスト操作とデータ管理を徹底的に学べます。例えば:

  • リストの作成、追加、削除、クリア操作
  • セッション状態を使ったデータの永続化
  • ランダム選択と動的なコンテンツ生成
  • ユーザーインターフェースの構築

プログラミングを楽しみながらリスト操作の概念を身に着けましょう!

📁 フォルダとファイルの作成

1. フォルダ構造

shopping-project/
├── shopping.py
└── requirements.txt

2. 必要なライブラリをインストール

まず、requirements.txtファイルに以下を書きます:

streamlit>=1.28.0
random>=3.12.0

これで、プロジェクトの準備が整いました!

🦘 買い物メモアプリを作ってみよう

さっそく、shopping.py にコードを書いていきましょう!

1️⃣📱 アプリの基本設定

まずは、アプリの基本設定から始めます。

# 必要なライブラリをインポート
import streamlit as st  # Webアプリ作成用
import random  # ランダム選択用

# ページ設定
st.set_page_config(
    page_title="オーストラリア食材買い物メモ",  # ブラウザのタブに表示されるタイトル
    page_icon="🦘",                            # ブラウザのタブに表示されるアイコン
    layout="wide"                              # レイアウトをワイドに設定
)

# タイトルと説明
st.title("🦘 オーストラリア食材買い物メモ")  # メインタイトル
st.markdown("---")  # 区切り線
st.markdown("### オーストラリアの美味しい食材や商品をリストアップしよう!")  # サブタイトル

cursor のターミナルで以下のコマンドを実行して画面表示を確認しましょう!

python -m streamlit run shopping.py

2️⃣📊 リストデータの準備

次に、オーストラリアの食材サンプルをリストとして準備します。

# ===== オーストラリアの食材サンプル(リスト) =====
# リスト(list):複数のデータを管理するデータ構造
# 角括弧[]で囲んで、カンマ区切りで要素を並べる
australian_foods = [
    "🍯 マヌカハニー",
    "🥩 ビーフジャーキー",
    "🍪 ティムタム",
    "🧀 ビタービター",
    "🍷 ワイン",
    "🦘 カンガルーミート",
    "🐊 クロコダイルミート",
    "🥜 マカダミアナッツ",
    "🍫 チョコレート",
    "☕ コーヒー豆",
    "🥛 ミルク",
    "🧈 バター",
    "🥖 食パン",
    "🍺 xxxx Gold (ビール)"
]

📝 リストの詳細説明:

  • リスト(list) - 複数のデータを順番に管理するデータ構造

    • 角括弧[]で囲んで、カンマ区切りで要素を並べる
    • 例:["アイテム1", "アイテム2", "アイテム3"]
    • インデックス(番号)で各要素にアクセス可能
    • 最初の要素はインデックス 0 から始まる
  • リストの特徴 - 変更可能(mutable)

    • 要素の追加、削除、変更が可能
    • 順番が保持される
    • 同じ要素を複数含むことができる

3️⃣🔄 セッション状態の初期化

買い物リストを保存する仕組みを準備します。

# ===== セッション状態の初期化 =====
# session_state:ページを更新してもデータを保持するStreamlitの機能
# 買い物リストを保存するための空のリストを作成
if 'shopping_list' not in st.session_state:
    st.session_state.shopping_list = []  # 空のリストで初期化

# 削除確認メッセージを表示するためのフラグ
if 'clear_clicked' not in st.session_state:
    st.session_state.clear_clicked = False  # Falseで初期化

📝 セッション状態の詳細説明:

  • st.session_state - ページを更新してもデータを保持する仕組み

    • 通常の変数はページを更新すると消える
    • session_stateを使うと、ページを更新してもデータが保持される
    • 買い物リストの永続化に最適
  • in演算子 - 辞書やリストにキーや要素が存在するかチェック

  • not in演算子 - 辞書やリストにキーや要素が存在しないかチェック

📝 innot in演算子の比較:

💻 innot in演算子のコード例

# ===== 基本的な使用例 =====
# 辞書の場合
my_dict = {"name": "John", "age": 25}

# in演算子(存在するかチェック)
if "name" in my_dict:
    print(f"名前: {my_dict['name']}")  # 存在する場合の処理

# not in演算子(存在しないかチェック)
if "city" not in my_dict:
    my_dict["city"] = "Tokyo"  # 存在しない場合の処理

# リストの場合
my_list = ["apple", "banana", "orange"]

# in演算子(存在するかチェック)
if "apple" in my_list:
    print("りんごが見つかりました!")

# not in演算子(存在しないかチェック)
if "grape" not in my_list:
    my_list.append("grape")  # 存在しない場合の処理

💡 使い分けのポイント:

  • in演算子: データが存在する場合の処理(表示、更新など)

  • not in演算子: データが存在しない場合の処理(初期化、作成など)

  • フラグ変数 - 状態を管理するための真偽値(True/False)

    • 例:clear_clicked = False
    • ボタンが押されたかどうかなどの状態を管理

4️⃣🎲 サイドバーとランダム機能

サイドバーにオーストラリア情報とランダム機能を追加します。

# ===== サイドバーにオーストラリア情報 =====
with st.sidebar:  # サイドバーを作成
    st.header("🇦🇺 オーストラリア情報")  # サイドバーのヘッダー
    st.markdown("""
    **オーストラリアのおすすめ料理:**
    - 🥩 ビーフステーキ
    - 🦘 カンガルーグリル
    - 🦞 ロブスター
    - 🦪 オイスター
    - 🍖 ラムチョップ
    """)

    # ===== ランダムなオーストラリア情報を表示 =====
    # リスト:複数の文字列を格納
    australia_facts = [
        "オーストラリアには世界最大のサンゴ礁、グレートバリアリーフがあります!",
        "オーストラリアの国土は日本の約20倍の大きさです!",
        "オーストラリアには世界で最も毒の強いヘビ🐍がいます!",
        "オーストラリアの羊の数は人口の約3倍です!",
        "オーストラリアには世界で最も古い砂漠があります!",
        "「アバター」という映画のオープニングはケアンズにある世界最古の熱帯雨林です!",
        "ブリスベンの川にはサメが住んでいます🦈",
        "ケアンズの川やビーチには時々ワニがいます🐊"
    ]

    # ボタンが押された時の処理
    if st.button("🎲 オーストラリア豆知識"):
        # random.choice()関数:リストからランダムに1つの要素を選択
        st.info(random.choice(australia_facts))

📝 サイドバーとランダム機能の詳細説明:

  • with st.sidebar: - サイドバーを作成するコンテキストマネージャー

    • サイドバー内の要素をグループ化
    • メインコンテンツとは別の領域に表示
  • st.markdown() - Markdown 形式のテキストを表示

    • 太字、リスト、リンクなどの書式が使える
    • 複数行の文字列は"""で囲む
  • random.choice()関数 - リストからランダムに 1 つの要素を選択

    • 例:random.choice(australia_facts)
    • 毎回異なる要素が選ばれる
  • st.info() - 情報メッセージを青色で表示

    • ユーザーに情報を伝えるのに適している

画面が以下のようになるはずです!「オーストラリア豆知識」ボタンも押して確認しましょう!

5️⃣📝 メインコンテンツとリスト操作

買い物リストの追加機能を実装します。

# ===== メインコンテンツ =====
st.header("📝 買い物リスト管理")  # メインのヘッダー

# 新しいアイテムの入力
# st.text_input():テキスト入力欄を作成
new_item = st.text_input("新しいアイテムを入力してください:", placeholder="例: マヌカハニー")

# ===== 追加ボタンの処理 =====
# st.button():ボタンを作成
if st.button("➕ リストに追加"):
    # strip()メソッド:文字列の前後の空白を削除
    if new_item.strip():  # 空でない場合のみ追加
        # append()メソッド:リストの末尾に要素を追加
        # これが今回の学習ポイントの1つ!
        st.session_state.shopping_list.append(new_item.strip())
        st.success(f"✅ '{new_item}' をリストに追加しました!")
    else:
        st.warning("⚠️ アイテム名を入力してください。")

# ===== サンプルアイテムを追加するボタン =====
if st.button("🎯 サンプル食材を追加"):
    # random.choice()関数:リストからランダムに1つの要素を選択
    sample_item = random.choice(australian_foods)
    # append()メソッド:リストに要素を追加
    st.session_state.shopping_list.append(sample_item)
    st.success(f"✅ '{sample_item}' をリストに追加しました!")

実際に入力して確認しましょう!

📝 リスト操作の詳細説明:

  • st.text_input() - テキスト入力欄を作成

    • placeholder - 入力欄に表示されるヒントテキスト
    • 戻り値:ユーザーが入力した文字列
  • strip()メソッド - 文字列の前後の空白を削除

    • 例:" hello ".strip()"hello"
    • ユーザーの入力ミスを防ぐのに重要
  • append()メソッド - リストの末尾に要素を追加

    • 例:shopping_list.append("新しいアイテム")
    • リストを変更する(元のリストに追加)
  • st.success()/warning() - 成功・警告メッセージを表示

    • success - 緑色(成功時)
    • warning - 黄色(警告時)
  • f-string - 文字列内に変数を埋め込む

    • 例:f" '{new_item}' をリストに追加しました!"
    • {}の中に変数や式を入れる

💡 リスト操作をわかりやすく図解化

6️⃣🗑️ 削除機能とメッセージ管理

リストの削除機能とメッセージ管理を実装します。

# ===== クリアメッセージの表示 =====
# セッション状態を使ってメッセージを管理
# クリアボタンが押されたらメッセージを表示
if st.session_state.clear_clicked:
    st.success("✅ リストをクリアしました!")
    # メッセージを表示したらフラグをリセット(ボタンが押されていない状態にする)
    st.session_state.clear_clicked = False  # フラグをリセット

# ===== 買い物リストの表示 =====
st.markdown("---")  # 区切り線
# 2つのカラムを作成(3:1の比率)
col1, col2 = st.columns([3, 1])
with col1:
    st.header("🛒 現在の買い物リスト")  # リストのヘッダー
with col2:
    # len()関数:リストの要素数を取得
    st.metric("アイテム数", len(st.session_state.shopping_list))

# ===== リストが空の場合のメッセージ =====
if len(st.session_state.shopping_list) == 0:
    st.info("📝 まだアイテムがありません。上記の入力欄からアイテムを追加してみましょう!")
else:
    # ===== for文を使ってリストの中身を順番に表示 =====
    # enumerate()関数:リストの要素とインデックスを同時に取得
    # enumerate(st.session_state.shopping_list, 1):インデックスを1から開始
    # これが今回の学習ポイントの1つ!
    for index, item in enumerate(st.session_state.shopping_list, 1):
        # 3つのカラムを作成(0.1:0.6:0.3の比率)
        col1, col2, col3 = st.columns([0.1, 0.6, 0.3])

        with col1:
            st.write(f"**{index}.**")  # 番号を表示

        with col2:
            st.write(item)  # アイテム名を表示

        with col3:
            # st.popover():ポップオーバー(小さなポップアップ)を作成
            with st.popover("🗑️ 削除", help=f"「{item}」を削除"):
                st.write(f"「{item}」を削除しますか?")
                if st.button("はい", key=f"confirm_yes_{index}"):
                    # pop()メソッド:指定したインデックスの要素を削除
                    st.session_state.shopping_list.pop(index - 1)
                    st.rerun()  # ページを再読み込み

アイテムを削除してみましょう!

📝 削除機能の詳細説明:

  • len()関数 - リストの要素数を取得

    • 例:len(["apple", "banana", "orange"]) → 3
    • 例:len([]) → 0(空のリスト)
  • enumerate()関数 - リストの要素に番号を付けて順番に取り出す

    • 例:enumerate(shopping_list, 1) - 1 から始まる番号を付ける
    • 例:for index, item in enumerate(["りんご", "バナナ"], 1):
      • index = 1, item = "りんご"
      • index = 2, item = "バナナ"
  • st.columns() - 複数のカラムを作成

    • 例:col1, col2, col3 = st.columns([0.1, 0.6, 0.3])
    • 比率を指定してレイアウトを調整
  • st.popover() - ポップオーバー(小さなポップアップ)を作成

    • 削除確認などの小さな UI に適している
    • helpパラメータでツールチップを表示
  • pop()メソッド - リストから指定した番号のアイテムを取り除く

    • 例:shopping_list.pop(0) - shopping_list の 1 番目のアイテムを削除
    • 例:shopping_list.pop(1) - shopping_list の 2 番目のアイテムを削除
    • 注意:番号は 0 から始まる(1 番目 = 0、2 番目 = 1)
  • st.rerun() - ページを再読み込み

    • 削除後に表示を更新するために使用

7️⃣📋 リスト操作ボタン

リストのクリアとコピー機能を実装します。

# ===== リストの操作ボタン =====
if len(st.session_state.shopping_list) > 0:
    st.markdown("---")  # 区切り線
    # 2つのカラムを作成
    col1, col2 = st.columns(2)

    with col1:
        # リストをクリアするボタン
        if st.button("🗑️ リストをクリア"):
            # clear()メソッド:リストの全要素を削除
            st.session_state.shopping_list.clear()
            st.session_state.clear_clicked = True  # メッセージ表示フラグを設定
            st.rerun()  # ページを再読み込み

    with col2:
        # リストをコピーするボタン
        if st.button("📋 リストをコピー"):
            # リストの要素を文字列に変換
            # enumerate()関数:インデックスと要素を同時に取得
            # join()メソッド:リストの要素を改行で結合
            list_text = "\n".join([f"{i+1}. {item}" for i, item in enumerate(st.session_state.shopping_list)])
            st.code(list_text)  # コードブロックとして表示
            st.info("上記のリストをコピーして使用してください!")

リストをコピーしたり、クリアしたりしてみましょう!

📝 リスト操作の詳細説明:

  • clear()メソッド - リストの全要素を削除

    • 例:shopping_list.clear()
    • 空のリストになる
  • リスト内包表記 - for 文を短く書く方法

    • 例:[f"{i+1}. {item}" for i, item in enumerate(shopping_list)]
    • これは以下の for 文と同じ意味:
      result = []
      for i, item in enumerate(shopping_list):
          result.append(f"{i+1}. {item}")
      
  • join()メソッド - リストのアイテムを文字列でつなげる

    • 例:"\n".join(["りんご", "バナナ", "オレンジ"])
    りんご
    バナナ
    オレンジ
    

    \nは改行を表す特殊文字です。)

    • 例:", ".join(["りんご", "バナナ", "オレンジ"]) → "りんご, バナナ, オレンジ"
  • st.code() - コードブロックとして表示

    • コピーしやすい形式で表示
    • モノスペースフォントで表示

🎉 完成!

おめでとうございます!

今回出来上がった画面はこちらです 👇

実際に様々な食材を追加・削除して動作確認してみましょう!!

🎯 まとめ:買い物メモアプリで学んだこと

今回作成した買い物メモアプリは、以下のような多くの重要な概念が含まれています:

  • リスト操作 - プログラミングの基本データ構造
  • セッション状態管理 - データの永続化
  • ユーザー入力処理 - インタラクティブなアプリの作成
  • ランダム処理 - 動的なコンテンツの生成
  • UI/UX 設計 - 使いやすいインターフェースの構築

今回の買い物メモアプリの特徴:

  • リスト管理 - 追加、削除、クリア、表示機能
  • ランダム機能 - サンプル食材の追加と豆知識
  • セッション状態 - ページ更新後もデータを保持
  • レスポンシブデザイン - カラムレイアウトで見やすく
  • ユーザーフレンドリー - 直感的な操作とメッセージ

🚀 次のステップ

今回学んだリスト操作を応用して、以下のような機能を追加してみましょう:

  1. カテゴリ分け - 食材、飲み物、お土産などで分類
  2. 優先度設定 - 重要度に応じた並び替え
  3. 価格管理 - 予算計算機能の追加
  4. データの永続化 - ファイルに保存する機能
  5. 検索機能 - リスト内のアイテム検索

プログラミングは、このように少しずつ機能を追加していくことで、どんどん面白くなります!今回学んだリスト操作は、プログラミングの基本中の基本なので、しっかりと理解しておきましょう!


🎓 プログラミング学習におすすめ

プログラミング未経験の方には CyTech(サイテック) がおすすめです!

CyTech は、未経験から IT エンジニアを目指す人向けのオンライン学習プラットフォームで、基礎から実務レベルのスキルを最短 10 ヶ月で習得できるカリキュラムを提供しています。
HTML/CSS/JavaScript/PHP/SQL/Git などのプログラミング言語に加え、デザイン、英語なども学べる総合的なプラットフォームです。
今後随時学習できるプログラミング言語増加予定!
エンジニア学習にお困りの方はまずは CyTech 無料カウンセリングでお悩み解消!

Discussion