
Table of Contents(目次)
クラスを使いこなすためのテクニック
この回では、Pythonのクラスをより安全で拡張性のある形で設計する方法を学びます。特殊メソッド、カプセル化、@property、コンストラクタ・デストラクタの使い方を順番に見ていきましょう。
特殊メソッド(マジックメソッド)
特殊メソッドの基本
Pythonでは、print() や == などの操作を自分のクラスでも自然に使えるようにするための仕組みがあります。それが「特殊メソッド(マジックメソッド)」です。__str__ を定義すると print(car) で分かりやすい文字列を表示でき、__eq__ を定義すると car1 == car2 のようにオブジェクト同士を比較できるようになります。
class Car:
def __init__(self, brand, model):
self.brand = brand
self.model = model
def __str__(self):
return f'{self.brand} {self.model}'
def __eq__(self, other):
return self.brand == other.brand and self.model == other.model
出力例
car1 = Car('Toyota', 'Corolla')
car2 = Car('Toyota', 'Corolla')
car3 = Car('Tesla', 'Model 3')
print(car1) # Toyota Corolla
print(car3) # Tesla Model 3
print(car1 == car2) # True
print(car1 == car3) # False
特殊メソッドの種類
今回の例で使用したもの:
__str__:print()で表示される文字列を定義__eq__:==演算子での比較を定義
その他の主な特殊メソッド(代表例):
__repr__:repr()や対話型での表示用__add__,__sub__など算術演算子__len__:len()に対応__getitem__,__setitem__: インデックス操作に対応__iter__,__next__: イテレーション対応
特殊メソッドの全種類のリストはこちら(公式ドキュメント): https://docs.python.org/ja/3.14/reference/datamodel.html#emulating-callable-objects
カプセル化とアクセス制御
クラスの中には、外部から触ってほしくないデータがあります。変数名の前に _ や __ を付けることでアクセス制御ができます。
_speedはあくまで「内部用」として扱い、直接外部から書き換えないことが推奨されます。__engine_onは外部から直接触れないように隠しているので、必ずstart_engine/stop_engine経由で操作します。
こうすることで、Carクラスのエンジンの状態や速度の管理を安全に行えます。
class Car:
def __init__(self, speed):
self._speed = speed # 内部用目印
self.__engine_on = False # 強制的に隠す
def start_engine(self):
self.__engine_on = True
print(f'{self.brand} {self.model}のエンジンを始動しました')
def stop_engine(self):
self.__engine_on = False
print(f'{self.brand} {self.model}のエンジンを停止しました')
my_car = Car(50)
print(my_car._speed) # 50 (アクセスできますが、推奨されません)
print(my_car.__engine_on) # エラーが発生:AttributeError: 'Car' object has no attribute '__engine_on'
@property デコレーターで安全に属性を操作
@propertyを使うと、変数の「取得する処理」と「代入する処理」を同じ名前で統一できます。例えば、speedという変数を扱うように、値の取得と代入を行うことができます。通常の変数と違うところは、代入するときに「負の数は入れない」というようなチェックを入れることができます。これにより、変数_speedに直接触らず安全に操作できます。
- getterメソッド
- メソッドの定義の前に
@propertyを付けます。 - getterメソッドは値を返します。
- メソッドの定義の前に
- setterメソッド
- メソッドの定義の前に
@メソッド名.setter(今回の場合は@speed.setter)を付けます。 - メソッド名はgetterメソッドと同じです。
- 代入される値が引数として渡されます。
- 渡された値をチェックして、エラーを発生させるなどの処理を加えることができます。
- メソッドの定義の前に
class Car:
def __init__(self, brand, model, speed):
self.brand = brand
self.model = model
self._speed = speed # 内部変数
@property
def speed(self):
# 値を取得するための getter メソッド
return self._speed
@speed.setter
def speed(self, value):
# 値を設定する setter メソッド
# 0未満はエラーとして扱う
if value < 0:
raise ValueError('速度は0以上で指定してください')
else:
self._speed = value
処理・出力例
car = Car('Toyota', 'Corolla', 50)
print(car.speed) # 50
car.speed = 80
print(car.speed) # 80
car.speed = -10 # ValueError: 速度は0以上で指定してください
コンストラクタ・デストラクタ
コンストラクタ(__init__)はインスタンス生成時に自動で呼ばれるメソッドで、初期設定や準備処理に使えます。デストラクタ(__del__)はインスタンス破棄時に自動で呼ばれ、終了処理やリソース解放に使います。
例えば通信クラスでは、__init__ で接続準備、__del__ で安全に接続を切断するイメージです。
class NetworkController:
def __init__(self, host, port):
self.host = host
self.port = port
print(f'{self.host}:{self.port}に接続準備をしました(コンストラクタ)')
def __del__(self):
print(f'{self.host}:{self.port}の接続を安全に切断しました(デストラクタ)')
nc = NetworkController('192.168.1.10', 8080)
del nc
出力例
192.168.1.10:8080に接続準備をしました(コンストラクタ)
192.168.1.10:8080の接続を安全に切断しました(デストラクタ)
デストラクタは、明示的にdel文を使用してオブジェクトを削除するか、関数などの処理が終了した時にPythonが自動的にオブジェクトを削除する時に実行されます。del nc行をコメントアウトして実行しても、デストラクタの処理が走ります。
実践例:安全で拡張性のあるクラス設計
共通操作はメソッドで制御し、属性は @property で安全に扱い、表示は __str__ で分かりやすくする。これらを組み合わせることで、安全で拡張性のあるクラス設計が可能です。
class Car:
def __init__(self, brand, model, speed):
self.brand = brand
self.model = model
self._speed = speed
self.__engine_on = False
def start_engine(self):
self.__engine_on = True
def stop_engine(self):
self.__engine_on = False
@property
def speed(self):
return self._speed
@speed.setter
def speed(self, value):
# 0未満はエラーとして扱う
if value < 0:
raise ValueError('速度は0以上で指定してください')
else:
self._speed = value
def __str__(self):
return f'{self.brand} {self.model} ({self._speed}km/h)'






