1. 型の検査と継承関係の確認
Pythonでは、オブジェクトの型やクラスの継承関係を動的に確認するための組み込み関数が用意されています。
class Device:
pass
class Laptop(Device):
pass
macbook = Laptop()
# インスタンスの型を確認
print(isinstance(macbook, Laptop)) # True
print(isinstance(macbook, Device)) # True (継承関係も考慮される)
# クラスの継承関係を確認
print(issubclass(Laptop, Device)) # True
print(issubclass(Device, Laptop)) # False
2. リフレクション(内省)
リフレクションとは、プログラムの実行中にオブジェクトの属性やメソッドを操作する能力のことです。Pythonでは主に4つの関数を使用します。
class WebServer:
def __init__(self, host, port):
self.host = host
self.port = port
def start(self):
print(f"Server starting on {self.host}:{self.port}")
server = WebServer("localhost", 8080)
# 属性の存在確認
if hasattr(server, "start"):
# 属性の取得
method = getattr(server, "start")
method()
# 属性の動的な設定
setattr(server, "protocol", "HTTPS")
print(server.protocol)
# 属性の削除
delattr(server, "port")
これらの手法は、プラグインシステムの構築や動的なルーティング処理などで非常に有効です。
3. 特殊メソッドによるオブジェクトのカスタマイズ
Pythonのクラスは、ダブルアンダースコア(`__`)で囲まれた特殊メソッドを定義することで、演算子や組み込み関数の挙動をカスタマイズできます。
文字列表現(__str__ と __repr__)
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def __str__(self):
# print() や str() で呼ばれる
return f"商品名: {self.name}"
def __repr__(self):
# 開発用・デバッグ用の表現
return f"Product(name='{self.name}', price={self.price})"
item = Product("Laptop", 150000)
print(item) # 商品名: Laptop
print(repr(item)) # Product(name='Laptop', price=150000)
コンテナとしての振る舞い(Itemシリーズ)
辞書のように角括弧 `[]` を使ってアクセスできるようにします。
class CustomConfig:
def __init__(self):
self._data = {}
def __setitem__(self, key, value):
self._data[key] = value
def __getitem__(self, key):
return self._data.get(key, "Not Found")
def __delitem__(self, key):
if key in self._data:
del self._data[key]
config = CustomConfig()
config["timeout"] = 30
print(config["timeout"]) # 30
4. インスタンス生成の制御とシングルトン
`__new__` は実際のインスタンスを生成するメソッドで、`__init__` より先に実行されます。これを利用して、クラスから一つのインスタンスしか生成されない「シングルトン」を実現できます。
class DatabaseConnection:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, db_name):
# 既に初期化されている場合はスキップする等のロジック
self.db_name = db_name
db1 = DatabaseConnection("Postgres")
db2 = DatabaseConnection("MySQL")
print(db1 is db2) # True (同一インスタンス)
5. 高度なデコレータ:@property, @classmethod, @staticmethod
クラスの設計をより洗練させるために使用されます。
class Employee:
bonus_rate = 0.1
def __init__(self, salary):
self._salary = salary
@property
def total_income(self):
"""メソッドを属性のように呼び出す"""
return self._salary * (1 + self.bonus_rate)
@classmethod
def set_bonus(cls, new_rate):
"""クラス全体の状態を変更する"""
cls.bonus_rate = new_rate
@staticmethod
def is_work_day(day):
"""インスタンスやクラスの状態に依存しないユーティリティ"""
return day not in ["Saturday", "Sunday"]
emp = Employee(500000)
print(emp.total_income) # 550000.0
Employee.set_bonus(0.2)
print(emp.total_income) # 600000.0
6. 多重継承とMRO(メソッド解決順序)
Python 3では「新式クラス」が採用されており、多重継承時のメソッド探索順序は「C3線形化」アルゴリズムに従います。`mro()` メソッドでその順序を確認できます。
class A:
def greet(self): print("A")
class B(A):
def greet(self): print("B")
class C(A):
def greet(self): print("C")
class D(B, C):
pass
d = D()
d.greet() # B
print(D.mro()) # [D, B, C, A, object]