基礎

Pythonのクラス|オブジェクト指向プログラミングの基本

クラスは、データ(属性)と処理(メソッド)をひとまとめにした設計図です。クラスから作られた実体を「インスタンス」と呼びます。オブジェクト指向プログラミングの基本であり、大規模なプログラムを整理するために欠かせない概念です。

この記事では、クラスの定義方法から、コンストラクタ、メソッド、属性の使い方まで詳しく解説します。

基本的な使い方

classキーワードでクラスを定義します。__init__メソッド(コンストラクタ)でインスタンスの初期化を行います。

Python
class User:
    def __init__(self, name, age):
        self.name = name  # インスタンス属性
        self.age = age
    
    def greet(self):
        print(f"こんにちは、{self.name}です。{self.age}歳です。")

# インスタンスの作成
user1 = User("太郎", 25)
user2 = User("花子", 30)

user1.greet()
user2.greet()

# 属性へのアクセス
print(f"名前: {user1.name}")
print(f"年齢: {user2.age}")
実行結果
こんにちは、太郎です。25歳です。
こんにちは、花子です。30歳です。
名前: 太郎
年齢: 30
selfとは

selfはインスタンス自身を参照する特別な引数です。メソッドの第1引数には必ずselfを書きます。呼び出し時には自動的に渡されるため、明示的に指定する必要はありません。

メソッドの種類

Python
class Calculator:
    # クラス属性(全インスタンスで共有)
    history = []
    
    def __init__(self, name="電卓"):
        self.name = name  # インスタンス属性
    
    # インスタンスメソッド
    def add(self, a, b):
        result = a + b
        Calculator.history.append(f"{a} + {b} = {result}")
        return result
    
    # クラスメソッド
    @classmethod
    def show_history(cls):
        for record in cls.history:
            print(record)
    
    # 静的メソッド
    @staticmethod
    def is_even(num):
        return num % 2 == 0

calc = Calculator("マイ電卓")
print(calc.add(3, 5))
print(calc.add(10, 20))

Calculator.show_history()
print(Calculator.is_even(4))
実行結果
8
30
3 + 5 = 8
10 + 20 = 30
True

特殊メソッド(マジックメソッド)

アンダースコア2つで囲まれた特殊メソッドを定義すると、組み込み関数や演算子の動作をカスタマイズできます。

Python
class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price
    
    def __str__(self):
        return f"{self.name}: {self.price:,}円"
    
    def __repr__(self):
        return f"Product('{self.name}', {self.price})"
    
    def __eq__(self, other):
        return self.price == other.price
    
    def __lt__(self, other):
        return self.price < other.price

p1 = Product("りんご", 200)
p2 = Product("バナナ", 100)
p3 = Product("みかん", 200)

print(p1)           # __str__
print(repr(p1))     # __repr__
print(p1 == p3)     # __eq__: True
print(p2 < p1)      # __lt__: True

# sorted()でも使える
products = [p1, p2, p3]
for p in sorted(products):
    print(f"  {p}")
実行結果
りんご: 200円
Product('りんご', 200)
True
True
  バナナ: 100円
  りんご: 200円
  みかん: 200円

プロパティ

@propertyデコレータを使うと、メソッドを属性のようにアクセスできます。

Python
class Circle:
    def __init__(self, radius):
        self._radius = radius
    
    @property
    def radius(self):
        return self._radius
    
    @radius.setter
    def radius(self, value):
        if value < 0:
            raise ValueError("半径は0以上である必要があります")
        self._radius = value
    
    @property
    def area(self):
        return 3.14159 * self._radius ** 2

c = Circle(5)
print(f"半径: {c.radius}")
print(f"面積: {c.area:.2f}")

c.radius = 10
print(f"半径: {c.radius}")
print(f"面積: {c.area:.2f}")
実行結果
半径: 5
面積: 78.54
半径: 10
面積: 314.16
クラス属性とインスタンス属性の違い

クラス属性は全インスタンスで共有されます。リストや辞書などのミュータブルなクラス属性を変更すると、全インスタンスに影響します。インスタンスごとに独立したデータが必要な場合は、__init__内でインスタンス属性として定義しましょう。

まとめ

  • classでデータと処理をまとめた設計図を定義する
  • __init__でインスタンスの初期化、selfでインスタンス自身を参照
  • 特殊メソッド(__str__, __eq__等)で組み込み操作をカスタマイズ
  • @propertyで属性のようにアクセスできるメソッドを定義
  • クラス属性とインスタンス属性の違いを理解する