← Назад к вопросам
Реализация Singleton на Python
1.2 Junior🔥 121 комментариев
#DevOps и инфраструктура#Django
Условие
Реализуйте паттерн Singleton несколькими способами:
- С использованием метаклассов
- С использованием декоратора
- С использованием new
Объясните плюсы и минусы каждого подхода.
Требования
- При создании нескольких экземпляров класса должен возвращаться один и тот же объект
- Решение должно быть потокобезопасным
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерн Singleton на Python: 4 способа реализации
Почему Singleton важен?
Singleton — паттерн, гарантирующий, что класс имеет только один экземпляр, и предоставляет глобальную точку доступа к нему.
Способ 1: Метакласс
import threading
class SingletonMeta(type):
_instances = {}
_lock = threading.Lock()
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
with cls._lock:
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
class Database(metaclass=SingletonMeta):
def __init__(self):
self.connection = None
Плюсы: Чистый Python, явное поведение, потокобезопасно. Минусы: Требует понимания метаклассов.
Способ 2: Декоратор
import threading
from functools import wraps
def singleton(cls):
instances = {}
lock = threading.Lock()
@wraps(cls)
def get_instance(*args, **kwargs):
if cls not in instances:
with lock:
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Logger:
def __init__(self):
self.logs = []
Плюсы: Просто использовать, минимум кода. Минусы: Теряется тип класса, IDE не распознаёт.
Способ 3: new
class ConfigManager:
_instance = None
_lock = threading.Lock()
def __new__(cls):
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
if not hasattr(self, '_initialized'):
self.config = {}
self._initialized = True
Плюсы: Прямой контроль, остаётся обычный класс. Минусы: init вызывается несколько раз, нужен флаг.
Способ 4: Модульный уровень
class _DatabaseConnection:
def __init__(self):
self.connection = None
db = _DatabaseConnection()
Плюсы: Самый Pythonic, встроенная потокобезопасность. Минусы: Нельзя переиспользовать для разных классов.
Сравнение
| Способ | Сложность | Потокобезопасность | Production |
|---|---|---|---|
| Метакласс | Средняя | Да | Отлично |
| Декоратор | Легкая | Да | Отлично |
| new | Средняя | Да | Хорошо |
| Модульный | Лёгкая | Да | Лучше |
Рекомендация
В production используй метакласс или модульный уровень. Декоратор хорош для прототипирования.