結論から言うと、単発の処理をまとめたいときは関数、状態を持つ対象を扱いたいときはクラスが向いています。
Pythonを学んでいると、「クラスを覚えたから何でもクラスにしたほうがよいのか」と迷うことがあります。
ですが、実際には関数で十分な場面も多く、無理にクラスへ寄せるとコードが重くなることもあります。
この記事では、クラスと関数をどう使い分けるかを、動くコードと一緒に整理します。
この記事でわかること
完成コード
完成コードは次の通りです。
def calculate_discounted_price(price, discount_rate):
return int(price * (1 - discount_rate))
class Coupon:
def __init__(self, code, discount_rate, remaining_uses):
self.code = code
self.discount_rate = discount_rate
self.remaining_uses = remaining_uses
def apply_to(self, price):
if self.remaining_uses <= 0:
raise ValueError("このクーポンはもう使えません。")
self.remaining_uses -= 1
return calculate_discounted_price(price, self.discount_rate)
print(calculate_discounted_price(5000, 0.2))
coupon = Coupon("SPRING20", 0.2, 2)
print(coupon.apply_to(5000))
print(coupon.remaining_uses)コードのポイント
このコードでは、単純な割引計算は関数にし、使用回数を持つクーポンはクラスにしています。
calculate_discounted_price()は、引数だけで完結する計算ですCouponは、割引率や残り使用回数という状態を持ちますapply_to()は、その状態を使いながら処理を行います
同じ「割引」に関するコードでも、状態を持つかどうかで向いている形が変わります。
コードを順番に説明します
主要な処理を分けて説明します。
1. 入力から結果を返すだけなら関数が向いています
def calculate_discounted_price(price, discount_rate):
return int(price * (1 - discount_rate))この関数は、価格と割引率を受け取り、割引後の価格を返すだけです。
前回の結果を覚える必要もなく、内部に状態を持つ必要もありません。
このように、引数を受け取って結果を返すだけの処理は、関数のほうがシンプルです。
無理にクラスへ入れなくても、十分に読みやすく保てます。
2. 状態を持つ対象はクラスにすると整理しやすくなります
class Coupon:
def __init__(self, code, discount_rate, remaining_uses):
self.code = code
self.discount_rate = discount_rate
self.remaining_uses = remaining_usesクーポンには、コード、割引率、残り使用回数のような情報があります。
こうした関連する値をまとめて扱いたいときは、クラスが向いています。
もし関数だけで扱うなら、毎回 code discount_rate remaining_uses を別々に渡す必要があり、更新も追いづらくなります。
状態を持つ対象はクラスにまとめると、何を扱っているかが明確になります。
3. 状態を読み書きする処理はクラスのメソッドに置くと自然です
def apply_to(self, price):
if self.remaining_uses <= 0:
raise ValueError("このクーポンはもう使えません。")
self.remaining_uses -= 1
return calculate_discounted_price(price, self.discount_rate)このメソッドは、割引を適用するだけでなく、残り使用回数も減らしています。
つまり、クーポンの状態を読み取り、更新する処理です。
このような処理は、関数よりクラスのメソッドにしたほうが自然です。
対象の状態と処理が近い場所にあるため、あとから読んでも流れを追いやすくなります。
実務で使うときのポイント
実務では、「その処理は前回の状態を覚える必要があるか」で考えると、クラスと関数を分けやすいです。
- 単純な変換や計算は、関数のままのほうが軽くて読みやすいです
- 複数の関連データをひとまとまりで扱うなら、クラスが向いています
- 状態更新がある処理は、クラスに寄せたほうが変更箇所を追いやすくなります
- 迷ったら、まず関数で考えて、状態を持つ必要が出てきたらクラスを検討すると整理しやすいです
たとえばCLIツールや業務スクリプトでも、文字列整形や集計は関数で十分です。
一方で、設定、接続情報、複数回使う処理対象などを持つなら、クラスにしたほうが保守しやすくなります。