採点されません。匿名です。 間違えることは学習の一部です。読むだけでもかまいません。

L07 ch02 — 普通のクラス

テクノロジ系 / L07 class — クラスとデータ構造

L07 ch02 — 普通のクラス

class 文で「データ + 振る舞い」をまとめる基本構文

ゴール

  • class 文でクラスを定義できる
  • __init__ で初期化引数を受け取れる
  • メソッド (self) で振る舞いを足せる
  • __repr__ で表示を整えられる

なぜ「普通のクラス」を学ぶか

  • @dataclass は「データだけ」を持つクラス向けの糖衣構文
  • データ + ロジック (振る舞い) を持たせたいときは class をそのまま書く
  • FastAPI のサービス層 / ドメイン層では普通のクラスが主役

最小例

class Counter:
    def __init__(self, start: int = 0):
        self.value = start          # 属性 (instance variable)

    def increment(self) -> None:
        self.value += 1              # 振る舞い (method)

c = Counter()
c.increment()
c.increment()
print(c.value)   # 2

__init__ と self

class User:
    def __init__(self, name: str, age: int):
        self.name = name             # self.X = X で属性に保存
        self.age = age

u = User("Taro", 30)
print(u.name, u.age)   # Taro 30
  • __init__ は「生成時に1回だけ呼ばれる」初期化メソッド
  • self は「いま生成中 / 操作中のそのインスタンス」を指す

メソッドを足す

class User:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    def greet(self) -> str:
        return f"Hi, I'm {self.name} ({self.age})"

    def have_birthday(self) -> None:
        self.age += 1

u = User("Taro", 30)
print(u.greet())          # Hi, I'm Taro (30)
u.have_birthday()
print(u.age)              # 31

__repr__ で「印刷時の見た目」を整える

class User:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

    def __repr__(self) -> str:
        return f"User(name={self.name!r}, age={self.age})"

u = User("Taro", 30)
print(u)   # User(name='Taro', age=30)

__repr__ 無しだと <__main__.User object at 0x10a...> でデバッグ困難。

dataclass との使い分け

普通のクラス@dataclass
__init__自分で書く自動生成
__repr__自分で書く自動生成
振る舞い (method)得意一応書ける
用途サービス / ロジックDTO / 値オブジェクト

→ 「振る舞いが主」なら普通のクラス、「データが主」なら dataclass

よくある間違い

# ❌ self を忘れる
class Counter:
    def __init__(start):     # self が無い
        value = start         # ローカル変数になる

# ❌ 属性とローカル変数の混同
class User:
    def __init__(self, name):
        name = name           # → self.name = name とすべき

# ❌ クラス変数とインスタンス変数の混同
class Cart:
    items = []                # ← 全インスタンスで共有される (危険)

drill

drill/BankAccount クラスを完成させる

拡張課題

  1. クラス変数 vs インスタンス変数
   class Dog:
       species = "Canis familiaris"   # クラス変数 (全 Dog 共通)
       def __init__(self, name):
           self.name = name           # インスタンス変数 (個別)
   
  1. @classmethod / @staticmethod
   class User:
       @classmethod
       def from_dict(cls, d: dict) -> "User":
           return cls(name=d["name"], age=d["age"])
   

よくある詰まり

症状原因対処
TypeError: __init__() missing 1 required positional argument: 'self'メソッドで self を書き忘れ第一引数に self を入れる
インスタンス間で list が共有されるクラス変数として [] を定義__init__ 内で self.items = []
AttributeError: ... has no attributeself.X = ... を書き忘れ__init__ 内で属性を初期化

次に学ぶ領域

領域続けて読む
dataclass (データ専用)ch01-dataclass
抽象基底クラス / Protocolch03 (予定)
継承Python 公式チュートリアル §9
力試ししたい方は クイズ形式の演習(任意) もあります。読むだけでも十分です。