タイトル: クラスの定義
SEOタイトル: Python クラスの定義 完全ガイド(class / __init__ / self / メソッド / 継承 / dataclass)
| この記事の要点 |
|
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