A Reusable Singleton Decorator

Step 4: A Reusable Singleton Decorator

Writing the instance and reset plumbing by hand for every class gets old. The Pythonic move is to capture the pattern once as a class decorator you can apply anywhere.

Implement singleton. It receives a class and returns a callable that, when called, always hands back one shared instance of that class:

  • Keep a per-decorator cache keyed by the class.
  • On the first call, build the instance with the given args and store it.
  • On every later call, return the stored instance and ignore new args.

The starter already applies singleton to a Database class. Your job is to make the decorator itself work. Each test defines its own decorated class, so they stay independent even though singleton state lives for the whole process.

Hints
Starter code
class Config:
    _instance = None

    def __init__(self):
        self._data = {}

    @classmethod
    def instance(cls):
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

    @classmethod
    def reset(cls):
        cls._instance = None

    def set(self, key, value):
        self._data[key] = value

    def get(self, key, default=None):
        return self._data.get(key, default)

    def has(self, key):
        return key in self._data


def singleton(cls):
    """Class decorator: make cls hand back one shared instance on every call."""
    # TODO: keep a per-class cache, create once on first call, reuse after
    pass


@singleton
class Database:
    def __init__(self):
        self.connections = 0
Write it on a laptop

The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.