hal
hal

Reputation: 841

What is the difference between two presented classes? Do they work differently?

What is the difference between this two implementations of Singleton. Does creating of variable _instance in parent class make it work differently from the second class?

class SingletonA(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = object.__new__(cls, *args, **kwargs)
        return cls._instance


class SingletonB(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = object.__new__(cls, *args, **kwargs)
        return cls._instance


# sample usage
class A(SingletonA):
    pass


print(A() == A()) #True

Upvotes: 1

Views: 48

Answers (2)

Menglong Li
Menglong Li

Reputation: 2255

Agreed with @Martijin Pieters answer,

Besides, provide another way to implement Singleton, called Borg, which share the same state:

class Borg:
    _shared_state = {}
    def __new__(cls, *args, **kwargs):
        obj = super(Borg, cls).__new__(cls, *args, **kwargs)
        obj.__dict__ = cls._shared_state
        return obj

class S1(Borg):
    pass

class S2(Borg):
    pass

assert S1() is not S1()
S1().v = 1
assert S1().v == S1().v
assert S1().v == S2().v


class S3(Borg):
    # if want to have a different state
    _shared_state = {}
    pass

S3().v = 2
assert S3().v != S1().v

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1122552

For the code posted, there is no difference.

If your subclasses implement __bool__ or __len__ however, the first example will fail, as not self._instance could return True even when an instance has been set. You really want to use if self._instance is None: instead:

>>> class AlwaysFalse(object):
...     def __bool__(self): return False
...
>>> if not AlwaysFalse():
...     print("It doesn't exist? Should we create a new one?")
...
It doesn't exist? Should we create a new one?
>>> AlwaysFalse() is None
False

Other than that, the differences are cosmetic.

You also want to use identity testing to check if a singleton implementation work correctly; a subclass could implement the __eq__ method and return True even if the two objects are distinct (so not singletons):

>>> class EqualNotSingleton(object):
...     def __eq__(self, other): return True
...
>>> EqualNotSingleton() == EqualNotSingleton()
True
>>> EqualNotSingleton() is EqualNotSingleton()
False

Upvotes: 6

Related Questions