記事一覧へ戻る 本の順番で続きを読む

オブジェクト指向プログラミング - クラスと継承

Python3中級 | 2026/02/18 15:44

オブジェクト指向プログラミング

クラスの基本

class User:
    """ユーザーを表すクラス"""

    # クラス変数(全インスタンスで共有)
    user_count = 0

    def __init__(self, name, age):
        """コンストラクタ"""
        self.name = name      # インスタンス変数
        self.age = age
        User.user_count += 1

    def greet(self):
        """インスタンスメソッド"""
        return f"こんにちは、{self.name}です({self.age}歳)"

    def __str__(self):
        """文字列表現"""
        return f"User({self.name}, {self.age})"

    def __repr__(self):
        return f"User(name='{self.name}', age={self.age})"

# インスタンスの作成
user = User("太郎", 25)
print(user.greet())     # こんにちは、太郎です(25歳)
print(User.user_count)  # 1

継承

class Employee(User):
    def __init__(self, name, age, company):
        super().__init__(name, age)  # 親クラスのコンストラクタ
        self.company = company

    def greet(self):
        """メソッドのオーバーライド"""
        return f"{self.company}{self.name}です"

emp = Employee("花子", 30, "ABC株式会社")
print(emp.greet())         # ABC株式会社の花子です
print(isinstance(emp, User))  # True

プロパティ

class Temperature:
    def __init__(self, celsius=0):
        self._celsius = celsius

    @property
    def celsius(self):
        return self._celsius

    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("絶対零度以下は設定できません")
        self._celsius = value

    @property
    def fahrenheit(self):
        return self._celsius * 9/5 + 32

temp = Temperature(100)
print(temp.celsius)     # 100
print(temp.fahrenheit)  # 212.0
temp.celsius = 0
print(temp.fahrenheit)  # 32.0

クラスメソッドとスタティックメソッド

class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    @classmethod
    def from_string(cls, date_str):
        """文字列からDateを作成(ファクトリメソッド)"""
        year, month, day = map(int, date_str.split('-'))
        return cls(year, month, day)

    @staticmethod
    def is_leap_year(year):
        """うるう年判定(インスタンス不要)"""
        return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)

date = Date.from_string("2026-03-15")
print(Date.is_leap_year(2024))  # True

抽象クラス

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14159 * self.radius ** 2

    def perimeter(self):
        return 2 * 3.14159 * self.radius

# shape = Shape()  # TypeError: 抽象クラスはインスタンス化できない
circle = Circle(5)
print(f"面積: {circle.area():.2f}")  # 面積: 78.54

データクラス(Python 3.7+)

from dataclasses import dataclass, field

@dataclass
class Product:
    name: str
    price: int
    quantity: int = 0
    tags: list = field(default_factory=list)

    @property
    def total(self):
        return self.price * self.quantity

p1 = Product("Python本", 3000, 2)
p2 = Product("Python本", 3000, 2)
print(p1)           # Product(name='Python本', price=3000, quantity=2, tags=[])
print(p1 == p2)     # True(値による比較)
print(p1.total)     # 6000

まとめ

  • class でクラスを定義、__init__ でコンストラクタ
  • super() で親クラスのメソッドを呼び出す
  • @property でゲッター/セッターを実装
  • @classmethod はクラスメソッド、@staticmethod はスタティックメソッド
  • ABC で抽象クラスを作る
  • @dataclass で簡潔にデータ保持クラスを作る