🧱 シングルトンは「モジュール」で作る
🧭 はじめに(What)
このページでは、Python におけるシングルトンの定石を整理する。 結論は明確で、Python ではシングルトンを「クラス」で作らない。 代わりに、モジュールそのものをシングルトンとして使うのが最も自然で、読みやすく、テストしやすい。
🎯 ねらい
🧱 問題の背景
Python でシングルトンを実装しようとすると、次のような設計に陥りがちだ。
__new__ オーバーライド
メタクラスを使った Singleton
スレッドセーフ性を理由に lock だらけの実装
これらは一見「ちゃんとしている」ように見えるが、Python では本質的に不要であることが多い。
Python では import は1回だけ評価され、以降は同じモジュールオブジェクトが再利用される という仕様がある。
❌ よくある誤解
🧬 __new__ をオーバーライドすべき?
🧠 メタクラス Singleton は高度で安全?
🧵 スレッドセーフにしないと危険?
スレッドセーフ性を理由に 先に複雑化するのは典型的な過剰設計。
💥 悪い例:クラスベース Singleton
class ConfigSingleton:
_instance = None
_lock = Lock()
def __new__(cls):
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
問題点
この種の実装は GoF の文脈を知らないと理解できない コードになりやすい。
✅ 良い例①:モジュールをそのまま使う
# config.py
DB_HOST = 'localhost'
DB_PORT = 5432
# usage.py
import config
print(config.DB_HOST)
なぜこれで十分か
import config は一度しか評価されない
すでに 「唯一のインスタンス」 が保証されている
読めば一発で意図が分かる
Python では モジュール = 自然な Singleton。
✅ 良い例②:遅延生成が必要な場合
# resource.py
_resource = None
def get_resource():
global _resource
if _resource is None:
_resource = create_resource()
return _resource
✅ 良い例③:lru_cache(maxsize=1) を使う
from functools import lru_cache
@lru_cache(maxsize=1)
def get_config():
return load_config()
cache_clear() でリセット可能
「一度だけ生成される関数」 という意図がコードから直接読める。
🧠 設計の要点
✅ チェックリスト
🔚 まとめ
Python においてシングルトンを「設計パターン」として実装しようとすると、 かえって Python らしさを損なう。
シンプルで、読めて、差し替えられる。 それが Python における正しい「唯一性」の設計である。