← Назад к вопросам

Реализация Singleton на Python

1.2 Junior🔥 121 комментариев
#DevOps и инфраструктура#Django

Условие

Реализуйте паттерн Singleton несколькими способами:

  1. С использованием метаклассов
  2. С использованием декоратора
  3. С использованием 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 используй метакласс или модульный уровень. Декоратор хорош для прототипирования.

Реализация Singleton на Python | PrepBro