この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:3
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: クラスの定義
SEOタイトル: Python クラスの定義 完全ガイド(class / __init__ / self / メソッド / 継承 / dataclass)

この記事の要点
  • Python のクラスは class クラス名: で定義し、初期化は __init__ メソッドで行う
  • self はインスタンス自身を指す慣習的な第一引数 — 省略不可
  • メソッドの種類: インスタンスメソッド / @classmethod (cls) / @staticmethod
  • 継承: class Child(Parent): — 多重継承も可。super() で親メソッド呼び出し
  • モダン Python: @dataclass デコレータで __init__ / __repr__ 等を自動生成

Python のクラス定義

Python のクラスはオブジェクトの設計図です。クラスからインスタンスを生成し、属性 (データ) とメソッド (振る舞い) をひとまとめに扱います。

基本構文

class クラス名:
    """ドキュメント文字列 (省略可)"""

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

    def __init__(self, arg1, arg2):
        """初期化メソッド (コンストラクタ相当)"""
        self.var1 = arg1
        self.var2 = arg2

    def some_method(self, x):
        """インスタンスメソッド"""
        return self.var1 + x

具体例

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def greet(self):
        return f"こんにちは、{self.name}です。{self.age}歳です。"

# インスタンス化と利用
alice = Person("Alice", 30)
bob = Person("Bob", 25)

print(alice.greet())  # こんにちは、Aliceです。30歳です。
print(bob.greet())    # こんにちは、Bobです。25歳です。

print(alice.name)     # Alice
alice.age = 31        # 属性の変更

self とは

selfインスタンス自身を指す変数で、メソッドの第一引数として必ず受け取ります。これは Python の規約で、名前は self でなくてもよいですが、必ず self と書くのが慣習です。

class Counter:
    def __init__(self):
        self.count = 0   # インスタンス変数

    def increment(self):
        self.count += 1  # self を介してインスタンス属性にアクセス

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

# self を省略すると AttributeError や TypeError になる

クラス変数とインスタンス変数

種類定義場所共有
クラス変数クラス直下全インスタンスで共有
インスタンス変数self.xxx = ...各インスタンス独立
class Dog:
    species = "Canis familiaris"   # クラス変数

    def __init__(self, name):
        self.name = name           # インスタンス変数

d1 = Dog("Pochi")
d2 = Dog("Tama")

print(d1.species, d2.species)   # Canis familiaris Canis familiaris (共有)
print(d1.name, d2.name)         # Pochi Tama (個別)

Dog.species = "Updated"          # クラス変数を変更すると全インスタンスに反映
print(d1.species)                # Updated

メソッドの種類

class MyClass:
    counter = 0

    def __init__(self, value):
        self.value = value
        MyClass.counter += 1

    # 1. インスタンスメソッド (self)
    def show(self):
        print(self.value)

    # 2. クラスメソッド (cls)
    @classmethod
    def get_count(cls):
        return cls.counter

    # 3. スタティックメソッド (引数なし、インスタンスにもクラスにも依存しない)
    @staticmethod
    def is_positive(n):
        return n > 0

a = MyClass(10)
b = MyClass(20)

a.show()                  # 10
print(MyClass.get_count())   # 2
print(MyClass.is_positive(5))  # True

継承

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return "..."

class Dog(Animal):   # Animal を継承
    def speak(self):
        return "ワン!"

class Cat(Animal):
    def __init__(self, name, color):
        super().__init__(name)    # 親の __init__ を呼ぶ
        self.color = color

    def speak(self):
        return "ニャー!"

dog = Dog("Pochi")
cat = Cat("Tama", "茶")
print(dog.speak())   # ワン!
print(cat.speak())   # ニャー!
print(cat.color)     # 茶

特殊メソッド (dunder)

Python は __name__ 形式の特殊メソッドを多数用意。演算子オーバーロードや組み込み関数の挙動をカスタマイズできます。

メソッド呼ばれる場面
__init__インスタンス生成時
__repr__repr(obj) / 対話シェル表示
__str__str(obj) / print(obj)
__eq__== 比較
__lt__< 比較
__len__len(obj)
__iter__for x in obj
__call__obj() として呼び出し
class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __repr__(self):
        return f"Point({self.x}, {self.y})"

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

p1 = Point(1, 2)
p2 = Point(3, 4)
print(p1 + p2)         # Point(4, 6)
print(p1 == Point(1,2))  # True

@dataclass — ボイラープレート削減

Python 3.7 以降、@dataclass デコレータで __init__ / __repr__ / __eq__ を自動生成できます。データ保持専用クラスなら大幅な記述削減になります。

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

p = Point(1, 2)
print(p)         # Point(x=1, y=2)
print(p == Point(1, 2))  # True

プロパティ (getter / setter)

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(c.radius)   # 5
print(c.area)     # 78.53...
c.radius = 10
# c.radius = -1   # ValueError

FAQ

Q: __init__ はコンストラクタ?
A: 厳密には初期化メソッド。インスタンス生成自体は __new__ が担当する。通常は __init__ だけ意識すれば OK。

Q: private はある?
A: 言語仕様上はない。慣習として _name は内部利用、__name はネームマングリングで擬似的に隠蔽。

Q: 多重継承で困らない?
A: MRO (Method Resolution Order) で C3 線形化により解決される。複雑になりがちなのでmixin パターンに限定するのが推奨。

関連トピック

  • インスタンス化 / コンストラクタ
  • 継承 / オーバーライド / super()
  • 抽象基底クラス (ABC) / プロトコル
  • dataclass / NamedTuple / TypedDict