Python | 1 日 120 分 × 7 日アプリ学習:クラスで作る商品管理アプリ(中級編)

Web APP Python
スポンサーリンク

4日目のゴール

4日目のテーマは
「クラスで作った商品オブジェクトに“賢さ”を持たせて、並び替えや絞り込みを気持ちよく書けるようになること」 です。

ここまでであなたは、Product クラスを作り、
複数の商品オブジェクトをリストで管理し、
登録・一覧・更新・削除・ID検索までできるようになりました。

今日はそこに、

商品自身に「便利なメソッド」を足す
価格や在庫で絞り込み・並び替えをする
「クラス+オブジェクトだからこそ書けるきれいなコード」を体感する

ここを狙っていきます。


おさらい Product クラスと CRUD の形

Product クラスの基本形をもう一度確認する

まずは、今の Product クラスのイメージを整理します。

class Product:
    def __init__(self, product_id, name, price, stock):
        self.product_id = product_id
        self.name = name
        self.price = price
        self.stock = stock

    def show_info(self):
        print("=== 商品情報 ===")
        print(f"ID: {self.product_id}")
        print(f"名前: {self.name}")
        print(f"価格: {self.price} 円")
        print(f"在庫数: {self.stock}")
Python

ここで大事なのは、__init__
「この商品オブジェクトは、ID・名前・価格・在庫数を必ず持つ」
という“型の前提”を決めていることです。

そして show_info
「この商品自身が、自分の情報を表示する」
という“振る舞い”を表しています。

この「データ(属性)+振る舞い(メソッド)」のセットが、
クラスの本質です。

products リストと CRUD の関係

アプリ側では、複数の商品をこう持っていました。

products = []
Python

ここに、Product オブジェクトを追加していきます。

登録は「Product を作って products に追加する」。
一覧は「products をぐるっと回して show_info を呼ぶ」。
更新は「IDで見つけた Product の属性を書き換える」。
削除は「IDで見つけた Product を products から取り除く」。

つまり、
「Product という型」と「products というリスト」が
アプリの土台になっています。


商品に「賢さ」を足す メソッドを増やす

価格に税込み価格を計算するメソッドを足す

クラスの良さは、
「そのデータに関する処理を、そのクラスの中に書ける」ことです。

例えば、「税込み価格」を計算したくなったとします。
辞書でやるなら、外側で

price_with_tax = int(product["price"] * 1.1)
Python

のように書きますが、
クラスなら「商品自身に計算させる」ことができます。

class Product:
    def __init__(self, product_id, name, price, stock):
        self.product_id = product_id
        self.name = name
        self.price = price
        self.stock = stock

    def show_info(self):
        print("=== 商品情報 ===")
        print(f"ID: {self.product_id}")
        print(f"名前: {self.name}")
        print(f"価格: {self.price} 円")
        print(f"在庫数: {self.stock}")

    def price_with_tax(self, tax_rate=0.1):
        return int(self.price * (1 + tax_rate))
Python

ここで深掘りしたいポイントは三つです。

一つ目は、price_with_tax の最初の引数も self であること。
二つ目は、self.price を使って「この商品の価格」を参照していること。
三つ目は、tax_rate にデフォルト値 0.1(10%)を設定していること。

使う側は、こう書けます。

p = Product("p001", "ノートPC", 120000, 5)
print(p.price_with_tax())        # 132000
print(p.price_with_tax(0.08))    # 129600(8%の場合)
Python

「p に税込み価格を計算してもらう」という書き方が、
とても自然ですよね。

在庫が少ないかどうかを判定するメソッド

もう一つ、よくあるパターンとして
「在庫が少ない商品だけを知りたい」というニーズがあります。

これも、商品自身に「在庫が少ないかどうか」を判断させると、
コードがきれいになります。

class Product:
    def __init__(self, product_id, name, price, stock):
        self.product_id = product_id
        self.name = name
        self.price = price
        self.stock = stock

    def is_low_stock(self, threshold=3):
        return self.stock <= threshold
Python

ここでのポイントは、

self.stock を使って「この商品の在庫数」を見ていること。
threshold にデフォルト値を持たせて、「3個以下なら少ない」とみなしていること。
戻り値が True / False の「判定メソッド」になっていること。

使う側は、こう書けます。

p = Product("p002", "マウス", 1500, 2)
if p.is_low_stock():
    print("在庫が少ない商品です。")
Python

この「判定ロジックをクラスの中に閉じ込める」感覚は、
この先ずっと使うことになります。


在庫が少ない商品だけを一覧表示する

「オブジェクトのメソッド」を条件に使う

さっきの is_low_stock を使えば、
「在庫が少ない商品だけを表示する」関数は
とてもシンプルに書けます。

def show_low_stock_products(products):
    print("=== 在庫が少ない商品一覧 ===")

    found = False
    for product in products:
        if product.is_low_stock():
            product.show_info()
            print("----------")
            found = True

    if not found:
        print("在庫が少ない商品はありません。")
Python

ここで深掘りしたいのは、この一行です。

if product.is_low_stock():
Python

この条件は、
「この product が“在庫が少ない”と自分で判断するなら」
という意味になります。

もし、在庫が少ない基準を「5個以下」に変えたくなったら、
is_low_stock の中の threshold を変えるだけで済みます。

アプリ側のコードは一切変えなくていい。
これが「ロジックをクラスに閉じ込める」強さです。


価格で並び替えて表示する

sorted と key をオブジェクトに対して使う

次は、「価格の安い順に商品を並べて表示する」機能を作ります。

辞書のときと同じように、
sortedkey を使いますが、
今度は「オブジェクトの属性」を基準にします。

def show_products_sorted_by_price(products):
    print("=== 商品一覧(価格の安い順) ===")

    if not products:
        print("商品がまだ登録されていません。")
        return

    sorted_products = sorted(products, key=lambda p: p.price)

    for product in sorted_products:
        product.show_info()
        print(f"税込価格: {product.price_with_tax()} 円")
        print("----------")
Python

ここでの重要ポイントは三つです。

一つ目は、sorted(products, key=lambda p: p.price)
「Product オブジェクトの price 属性を基準に並び替えている」こと。

二つ目は、lambda p: p.price
「並び替えの基準となる値を取り出す小さな関数」になっていること。

三つ目は、並び替えた結果を sorted_products に入れ、
元の products は壊していないこと。

このパターンを覚えると、
「名前順」「在庫数順」なども簡単に書けます。

例えば、在庫の少ない順に並べたいなら、

sorted_products = sorted(products, key=lambda p: p.stock)
Python

とするだけです。


名前で並び替えるときの注意点

大文字・小文字を気にせず並べたい場合

商品名で並び替えるとき、
「A と a を同じように扱いたい」ことがよくあります。

その場合は、lower() を使って
「小文字にそろえた名前」を基準にします。

def show_products_sorted_by_name(products):
    print("=== 商品一覧(名前順) ===")

    if not products:
        print("商品がまだ登録されていません。")
        return

    sorted_products = sorted(products, key=lambda p: p.name.lower())

    for product in sorted_products:
        product.show_info()
        print("----------")
Python

ここでのポイントは、

p.name.lower() を key にしていることで、
「大文字・小文字の違いを無視した並び替え」になっていることです。


4日目版メニュー 絞り込みと並び替えを追加する

CRUD に「在庫チェック」と「ソート」を足す

ここまで作った機能を、メニューに組み込みます。

def show_menu():
    print("==========")
    print("商品管理アプリ(クラス編 4日目)")
    print("1: 商品を登録する")
    print("2: 商品一覧を表示する")
    print("3: 商品情報を更新する")
    print("4: 商品を削除する")
    print("5: 商品をIDで表示する")
    print("6: 在庫が少ない商品を表示する")
    print("7: 商品一覧(価格の安い順)")
    print("8: 商品一覧(名前順)")
    print("0: 終了")
    print("==========")
Python

main は、こうなります。

def main():
    products = []

    while True:
        show_menu()
        choice = input("番号を選んでください: ").strip()

        if choice == "1":
            add_product(products)
        elif choice == "2":
            show_all_products(products)
        elif choice == "3":
            update_product(products)
        elif choice == "4":
            delete_product(products)
        elif choice == "5":
            show_product_detail(products)
        elif choice == "6":
            show_low_stock_products(products)
        elif choice == "7":
            show_products_sorted_by_price(products)
        elif choice == "8":
            show_products_sorted_by_name(products)
        elif choice == "0":
            print("アプリを終了します。")
            break
        else:
            print("不正な入力です。0〜8 のどれかを選んでください。")
Python

これで、

登録
一覧
更新
削除
ID検索
在庫が少ない商品の絞り込み
価格順・名前順の並び替え

という、かなり“アプリらしい”機能がそろってきます。


「どこを変えれば何が変わるか」を意識する

ロジックはクラスに、操作はアプリ側に

今日のコードを通して、
こんな構造が見えてきたはずです。

在庫が少ない基準を変えたいときは、
Product クラスの is_low_stock を変えればいい。

税込み計算のルールを変えたいときは、
Product クラスの price_with_tax を変えればいい。

並び替えの基準を変えたいときは、
sorted(..., key=...) の部分だけを変えればいい。

つまり、

「商品というもののルール」は Product クラスの中に閉じ込める。
「商品をどう並べるか・どう見せるか」はアプリ側の関数で決める。

この役割分担が見えてくると、
コードが一気に整理されて見えます。


4日目のまとめ 今日つかんでほしい感覚

今日の本質は、これです。

クラスは「データ」と「そのデータに関するロジック」を一緒に持てる。
__init__ で「このオブジェクトが必ず持つ属性」を決める。
メソッドで「このオブジェクトに関する処理」を表現する。
オブジェクトのメソッドを条件や key に使うと、絞り込みや並び替えがとても書きやすくなる。
「どのロジックをクラスに置き、どのロジックをアプリ側に置くか」を意識すると、設計の感覚が育つ。

5日目以降は、
この商品管理アプリに「ファイル保存」「クラスでアプリ全体を表現する」などを足していきます。

今日の「クラスに賢さを持たせる」感覚は、
オブジェクト指向の世界に一歩踏み込んだ、とても大事な一歩です。

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