Creating a Singleton in Python

Creating a singleton in Python

Use a Metaclass

I would recommend Method #2, but you're better off using a metaclass than a base class. Here is a sample implementation:

class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]

class Logger(object):
__metaclass__ = Singleton

Or in Python3

class Logger(metaclass=Singleton):
pass

If you want to run __init__ every time the class is called, add

        else:
cls._instances[cls].__init__(*args, **kwargs)

to the if statement in Singleton.__call__.

A few words about metaclasses. A metaclass is the class of a class; that is, a class is an instance of its metaclass. You find the metaclass of an object in Python with type(obj). Normal new-style classes are of type type. Logger in the code above will be of type class 'your_module.Singleton', just as the (only) instance of Logger will be of type class 'your_module.Logger'. When you call logger with Logger(), Python first asks the metaclass of Logger, Singleton, what to do, allowing instance creation to be pre-empted. This process is the same as Python asking a class what to do by calling __getattr__ when you reference one of it's attributes by doing myclass.attribute.

A metaclass essentially decides what the definition of a class means and how to implement that definition. See for example http://code.activestate.com/recipes/498149/, which essentially recreates C-style structs in Python using metaclasses. The thread What are some (concrete) use-cases for metaclasses? also provides some examples, they generally seem to be related to declarative programming, especially as used in ORMs.

In this situation, if you use your Method #2, and a subclass defines a __new__ method, it will be executed every time you call SubClassOfSingleton() -- because it is responsible for calling the method that returns the stored instance. With a metaclass, it will only be called once, when the only instance is created. You want to customize what it means to call the class, which is decided by it's type.

In general, it makes sense to use a metaclass to implement a singleton. A singleton is special because is created only once, and a metaclass is the way you customize the creation of a class. Using a metaclass gives you more control in case you need to customize the singleton class definitions in other ways.

Your singletons won't need multiple inheritance (because the metaclass is not a base class), but for subclasses of the created class that use multiple inheritance, you need to make sure the singleton class is the first / leftmost one with a metaclass that redefines __call__ This is very unlikely to be an issue. The instance dict is not in the instance's namespace so it won't accidentally overwrite it.

You will also hear that the singleton pattern violates the "Single Responsibility Principle" -- each class should do only one thing. That way you don't have to worry about messing up one thing the code does if you need to change another, because they are separate and encapsulated. The metaclass implementation passes this test. The metaclass is responsible for enforcing the pattern and the created class and subclasses need not be aware that they are singletons. Method #1 fails this test, as you noted with "MyClass itself is a a function, not a class, so you cannot call class methods from it."

Python 2 and 3 Compatible Version

Writing something that works in both Python2 and 3 requires using a slightly more complicated scheme. Since metaclasses are usually subclasses of type type, it's possible to use one to dynamically create an intermediary base class at run time with it as its metaclass and then use that as the baseclass of the public Singleton base class. It's harder to explain than to do, as illustrated next:

# works in Python 2 & 3
class _Singleton(type):
""" A metaclass that creates a Singleton base class when called. """
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(_Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]

class Singleton(_Singleton('SingletonMeta', (object,), {})): pass

class Logger(Singleton):
pass

An ironic aspect of this approach is that it's using subclassing to implement a metaclass. One possible advantage is that, unlike with a pure metaclass, isinstance(inst, Singleton) will return True.

Corrections

On another topic, you've probably already noticed this, but the base class implementation in your original post is wrong. _instances needs to be referenced on the class, you need to use super() or you're recursing, and __new__ is actually a static method that you have to pass the class to, not a class method, as the actual class hasn't been created yet when it is called. All of these things will be true for a metaclass implementation as well.

class Singleton(object):
_instances = {}
def __new__(class_, *args, **kwargs):
if class_ not in class_._instances:
class_._instances[class_] = super(Singleton, class_).__new__(class_, *args, **kwargs)
return class_._instances[class_]

class MyClass(Singleton):
pass

c = MyClass()

Decorator Returning A Class

I originally was writing a comment but it was too long, so I'll add this here. Method #4 is better than the other decorator version, but it's more code than needed for a singleton, and it's not as clear what it does.

The main problems stem from the class being it's own base class. First, isn't it weird to have a class be a subclass of a nearly identical class with the same name that exists only in its __class__ attribute? This also means that you can't define any methods that call the method of the same name on their base class with super() because they will recurse. This means your class can't customize __new__, and can't derive from any classes that need __init__ called on them.

When to use the singleton pattern

Your use case is one of the better examples of wanting to use a singleton. You say in one of the comments "To me logging has always seemed a natural candidate for Singletons." You're absolutely right.

When people say singletons are bad, the most common reason is they are implicit shared state. While with global variables and top-level module imports are explicit shared state, other objects that are passed around are generally instantiated. This is a good point, with two exceptions.

The first, and one that gets mentioned in various places, is when the singletons are constant. Use of global constants, especially enums, is widely accepted, and considered sane because no matter what, none of the users can mess them up for any other user. This is equally true for a constant singleton.

The second exception, which get mentioned less, is the opposite -- when the singleton is only a data sink, not a data source (directly or indirectly). This is why loggers feel like a "natural" use for singletons. As the various users are not changing the loggers in ways other users will care about, there is not really shared state. This negates the primary argument against the singleton pattern, and makes them a reasonable choice because of their ease of use for the task.

Here is a quote from http://googletesting.blogspot.com/2008/08/root-cause-of-singletons.html:

Now, there is one kind of Singleton which is OK. That is a singleton where all of the reachable objects are immutable. If all objects are immutable than Singleton has no global state, as everything is constant. But it is so easy to turn this kind of singleton into mutable one, it is very slippery slope. Therefore, I am against these Singletons too, not because they are bad, but because it is very easy for them to go bad. (As a side note Java enumeration are just these kind of singletons. As long as you don't put state into your enumeration you are OK, so please don't.)

The other kind of Singletons, which are semi-acceptable are those which don't effect the execution of your code, They have no "side effects". Logging is perfect example. It is loaded with Singletons and global state. It is acceptable (as in it will not hurt you) because your application does not behave any different whether or not a given logger is enabled. The information here flows one way: From your application into the logger. Even thought loggers are global state since no information flows from loggers into your application, loggers are acceptable. You should still inject your logger if you want your test to assert that something is getting logged, but in general Loggers are not harmful despite being full of state.

Is there a simple, elegant way to define singletons?

I don't really see the need, as a module with functions (and not a class) would serve well as a singleton. All its variables would be bound to the module, which could not be instantiated repeatedly anyway.

If you do wish to use a class, there is no way of creating private classes or private constructors in Python, so you can't protect against multiple instantiations, other than just via convention in use of your API. I would still just put methods in a module, and consider the module as the singleton.

Explain python Singleton class

Ok, to go over this in painful detail:

class Singleton: implicitly inherits from Object because in python everything is an Object.

instance = None is only read at module load time, and sets the class level variable instance to be None one time but it can be over written by individual instances of the class Singleton.

def __new__(cls):
if cls.instance is None:
cls.instance = super().__new__(cls)
return cls.instance

(First off, I think that it's weird that they put "cls" in there, I know why they did it, because it's referring to the class overall and not a specific instance of that class. But, it can be confusing so someone who doesn't know what they're looking at. Anyway...)

__new__ is a magic function that is called before __init__, that is roughly analogous to allocating the space for the new instance of the class. Here, cls.instance was set to None on module load, and so every time a new Singleton is being created this test is done. Since cls.instance is set the first time a Singleton is created, the super().__new__(cls) is also only called once. The super class of Singleton is Object. So the behavior of the super().__new__(cls) is exactly what you'd expect it to be for any other class you create.

If, you are creating a second(, or third/fourth/fifth...) instance of Singleton then this super().__new__(cls) will not be called. Instead the class level variable instance is returned, meaning that no new instances of Singleton can be created.

When you print the instances of Singleton then you can see the memory address of 0x10dbc0f60 is the same for both "instances" because cls.instance is returned at __new__ time, which you can think of as memory allocation time, before __init__ is called.

This is a good way to do a Singleton pattern because in order to create a singleton class, now, all you have to do is inherit from Singleton and the heavy lifting is already done. You go ahead and use __init__ like you normally would, and don't worry about it. Every time you go to create a "new" instance of that class, you'll get the same instance back. Totally behind the scenes.

This is pretty advanced stuff, but look how simple it is. python is the best!

Singleton Pattern In Python

The first thing to keep in mind is Python is not Java. It's not as restrictive as other languages. As Guido says, "we're all adults here". Nothing really prevents you from doing most things in Python. The solution is "don't do that".

However, there are several ways to do singletons. Another way, one that looks more "natural" to a user, is to use a factory function that looks like a class instantiation. Here's an example.

class _Singleton:
_instance = None

def hello(self):
print("Hello!")


def Singleton():
if _Singleton._instance is None:
_Singleton._instance = _Singleton()
return _Singleton._instance



s1 = Singleton()
s2 = Singleton()

assert s1 is s2

How to create inmutable and singleton objects in python?

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)

Create singleton class in python by taking advantage of meta class

None of the uses of cls refer to the metaclass. They refer to the instance of the metaclass, either SingletonBaseClass or SingletonDerivedClass.

Looking up cls._instance when cls is SingletonBaseClass finds SingletonMetaClass._instance because SingletonBaseClass is an instance of SingletonMetaClass, and looking up attributes on an object also searches its class, even when the object is itself also a class.

Update a property in singleton (python)

You give very few specific details, so I'll give an answer that should work, but I don't know if that is what you wanted.

How about you store the current filename in a environment variable using os.environ?

You can modify the singleton function:

import os

def singleton(myClass):
...
if myClass not in instances:
kwargs['filename'] = os.environ['logger_filename'] # may raise KeyError
instances[myClass] = myClass(*args, **kwargs)
...

@singleton
class Logger(object):
def __init__(self, filename):
self.filename = filename
...

Or another option is to just modify the logger class:

import os

@singleton
class Logger(object):
def __init__(self):
self.filename = os.environ['logger_filename'] # may raise KeyError

With any of these two options you just have to modify the value of the environment variable to set a different target for your loggers:

import os
os.environ['logger_filename'] = 'f1.log'

b = Logger()
b.log.debug("hello there") # writes on 'f1.log'

os.environ['logger_filename'] = 'f2222.log'

c = Logger()
c.log.debug("hello there") # writes on 'f2222.log'

Creating Singleton class in Python and counting the number of instances

__new__ is called for every MyClass(...) call. If it didn't get called, it would not be able to return the singleton instance.

And when the __new__ method returns an object and that object is an instance of the cls argument passed to __new__ (or a subclass), then the __init__ method is also called.

So, for each MyClass(...) call, __new__ is called. The __new__ method always returns an instance of the current class, so __init__ is called, every time. It doesn't matter here that it is the same instance each time.

From the __new__ method documentation:

If __new__() returns an instance of cls, then the new instance’s __init__() method will be invoked like __init__(self[, ...]), where self is the new instance and the remaining arguments are the same as were passed to __new__().

You can see this happen if you add some print() calls in the methods:

>>> class Singleton(object):
... _instance = None
... def __new__(class_, *args, **kwargs):
... print(f'Calling {class_!r}(*{args!r}, **{kwargs!r})')
... if not isinstance(class_._instance, class_):
... print(f'Creating the singleton instance for {class_!r}')
... class_._instance = object.__new__(class_)
... return class_._instance
...
>>> class MyClass(Singleton):
... num_of_instances = 0
... def __init__(self, real=5, imaginary=6):
... print(f'Calling {type(self)!r}.__init__(self, real={real!r}, imaginary={imaginary!r})')
... self.real = real
... self.imaginary = imaginary
... MyClass.num_of_instances += 1
...
>>> a = MyClass(10, 20)
Calling <class '__main__.MyClass'>(*(10, 20), **{})
Creating the singleton instance for <class '__main__.MyClass'>
Calling <class '__main__.MyClass'>.__init__(self, real=10, imaginary=20)
>>> b = MyClass()
Calling <class '__main__.MyClass'>(*(), **{})
Calling <class '__main__.MyClass'>.__init__(self, real=5, imaginary=6)

You can't prevent the automatic __init__ call, at least not without overriding something else. If you want to avoid __init__ being called each time, you have some options:

You don't have to use an __init__ method on the subclass. You could invent your own mechanism, __new__ could look for a __singleton_init__ method and call that:

class Singleton(object):
_instance = None

def __new__(class_, *args, **kwargs):
if not isinstance(class_._instance, class_):
class_._instance = object.__new__(class_)
if hasattr(class_._instance, '__singleton_init__'):
class_._instance.__singleton_init__(*args, **kwargs)`
return class_._instance

or your __init__ method could check if there are already attributes set in vars(self) (or self.__dict__) and just not set attributes again:

class MyClass(Singleton):
def __init__(self, real=5, imaginary=6):
if vars(self):
# we already set attributes on this instance before
return
self.real = real
self.imaginary = imaginary

The __new__ and __init__ logic is implemented in type.__call__; you could create a metaclass that overrides that logic. While you could simply call __new__ only (and leave everything as is), it makes sense to make the metaclass responsible for handling the Singleton pattern:

class SingletonMeta(type):
def __new__(mcls, *args, **kwargs):
cls = super().__new__(mcls, *args, **kwargs)
cls._instance = None
return cls

def __call__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__call__(*args, **kwargs)
return cls._instance

then use this not as a base class but with metaclass=.... You can create an empty base class if that's easier:

class Singleton(metaclass=SingletonMeta):
pass

class MyClass(Singleton):
# ...

The above will call __new__ on the class, optionally followed by __init__ on the resulting instance, just once. The SingletonMeta.__call__ implementation then, forever after, returns the singleton instance without further calls:

>>> class SingletonMeta(type):
... def __new__(mcls, *args, **kwargs):
... cls = super().__new__(mcls, *args, **kwargs)
... cls._instance = None
... return cls
... def __call__(cls, *args, **kwargs):
... print(f'Calling {cls!r}(*{args!r}, **{kwargs!r})')
... if cls._instance is None:
... cls._instance = super().__call__(*args, **kwargs)
... return cls._instance
...
>>> class Singleton(metaclass=SingletonMeta):
... pass
...
>>> class MyClass(Singleton):
... def __init__(self, real=5, imaginary=6):
... print(f'Calling {type(self)!r}.__init__(self, real={real!r}, imaginary={imaginary!r})')
... self.real = real
... self.imaginary = imaginary
...
>>> a = MyClass(10, 20)
Calling <class '__main__.MyClass'>(*(10, 20), **{})
Calling <class '__main__.MyClass'>.__init__(self, real=10, imaginary=20)
>>> MyClass()
Calling <class '__main__.MyClass'>(*(), **{})
<__main__.MyClass object at 0x10bf33a58>
>>> MyClass() is a
Calling <class '__main__.MyClass'>(*(), **{})
True
>>> MyClass().real
Calling <class '__main__.MyClass'>(*(), **{})
10


Related Topics



Leave a reply



Submit