Home > Software engineering >  How to create inmutable and singleton objects in python?
How to create inmutable and singleton objects in python?

Time:05-08

I'm trying to create a class that holds some data and is "shared" in all the code. Like the strings in Python: they are shared everywhere, as they are immutable, and only one instance with a particular value exists. I want to create the class on demand, but every time I create that class with the same parameters, I want to get the same object.

I wrote the following code:

class Data:

    _instances: dict[str, "Data"] = {}

    def __new__(cls, data: str) -> "Data":
        if data not in cls._instances:
            cls._instances[data] = super().__new__(cls)

        return cls._instances[data]

    def __init__(self, data: str) -> None:
        self._data = data

    @property
    def data(self) -> str:
        return self._data

    @data.setter
    def data(self, data: str) -> None:
        raise KeyError("Cannot change an immutable object")

It seems to work, but I have a feeling of not using all the tools Python gives us to handle this cases.

Is there any way to implement this with dataclasses? Or a more pythonic code to achieve the same?

CodePudding user response:

You can define an immutable dataclass with the frozen=True parameter. Making a dataclass frozen automatically makes it hashable, so you can just use functools.cache instead of implementing your own cache:

from dataclasses import dataclass
from functools import cache

@dataclass(frozen=True)
class Data:
    data: str

    @cache
    def __new__(cls, data: str) -> "Data":
        return super().__new__(cls)

x = Data("foo")
y = Data("foo")
assert id(x) == id(y)
  • Related