Creando un singleton en Python

Esta pregunta no es para la discusión de si el patrón de diseño de singleton es deseable o no, es un antipatrón, o para cualquier guerra religiosa, sino para discutir cómo este patrón se implementa mejor en Python de tal manera que sea la más python. En este caso, defino que “la mayoría de los pitones” significa que sigue el “principio de menos asombro” .

Tengo varias clases que se convertirían en singletons (mi caso de uso es para un registrador, pero esto no es importante). No deseo saturar varias clases con gumph agregado cuando simplemente puedo heredar o decorar.

Mejores métodos:


Método 1: un decorador

def singleton(class_): instances = {} def getinstance(*args, **kwargs): if class_ not in instances: instances[class_] = class_(*args, **kwargs) return instances[class_] return getinstance @singleton class MyClass(BaseClass): pass 

Pros

  • Los decoradores son aditivos de una manera que a menudo es más intuitiva que la herencia múltiple.

Contras

  • Mientras que los objetos creados usando MyClass () serían verdaderos objetos singleton, MyClass en sí misma es una función, no una clase, por lo que no puede llamar métodos de clase desde ella. También para m = MyClass(); n = MyClass(); o = type(n)(); m = MyClass(); n = MyClass(); o = type(n)(); entonces m == n && m != o && n != o

Método 2: una clase base

 class Singleton(object): _instance = None def __new__(class_, *args, **kwargs): if not isinstance(class_._instance, class_): class_._instance = object.__new__(class_, *args, **kwargs) return class_._instance class MyClass(Singleton, BaseClass): pass 

Pros

  • Es una verdadera clase

Contras

  • Herencia múltiple – eugh! __new__ podría sobrescribirse durante la herencia de una segunda clase base? Hay que pensar más de lo necesario.

Método 3: una metaclase

 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] #Python2 class MyClass(BaseClass): __metaclass__ = Singleton #Python3 class MyClass(BaseClass, metaclass=Singleton): pass 

Pros

  • Es una verdadera clase
  • Auto-mágicamente cubre la herencia.
  • Utiliza __metaclass__ para su propósito apropiado (y me hizo consciente de ello)

Contras

  • Hay alguna

Método 4: decorador devolviendo una clase con el mismo nombre

 def singleton(class_): class class_w(class_): _instance = None def __new__(class_, *args, **kwargs): if class_w._instance is None: class_w._instance = super(class_w, class_).__new__(class_, *args, **kwargs) class_w._instance._sealed = False return class_w._instance def __init__(self, *args, **kwargs): if self._sealed: return super(class_w, self).__init__(*args, **kwargs) self._sealed = True class_w.__name__ = class_.__name__ return class_w @singleton class MyClass(BaseClass): pass 

Pros

  • Es una verdadera clase
  • Auto-mágicamente cubre la herencia.

Contras

  • ¿No hay una sobrecarga para crear cada nueva clase? Aquí estamos creando dos clases para cada clase que deseamos hacer un singleton. Si bien esto está bien en mi caso, me preocupa que esto no pueda escalar. Por supuesto, hay una cuestión de debate sobre si sería demasiado fácil escalar este patrón …
  • ¿Cuál es el punto del atributo _sealed
  • No se pueden llamar a los métodos del mismo nombre en las clases base con super() porque se repetirán. Esto significa que no puede personalizar __new__ y no puede subclasificar una clase que necesita que llame a __init__ .

Usa una metaclase

Recomendaría el Método # 2 , pero es mejor usar una metaclase que una clase base. Aquí hay una implementación de ejemplo:

 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 

O en Python3

 class Logger(metaclass=Singleton): pass 

Si desea ejecutar __init__ cada vez que se llama a la clase, agregue

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

a la sentencia if en Singleton.__call__ .

Unas palabras sobre las metaclases. Una metaclase es la clase de una clase ; es decir, una clase es una instancia de su metaclase . Encontrará la metaclase de un objeto en Python con type(obj) . Las clases normales de nuevo estilo son de tipo type . Logger en el código anterior será de la class 'your_module.Singleton' de tipo class 'your_module.Singleton' , así como la (única) instancia de Logger será de la class 'your_module.Logger' de tipo class 'your_module.Logger' . Cuando llama al registrador con el registrador Logger() , Python primero le pregunta a la metaclase del Logger , Singleton , qué hacer, permitiendo que la creación de instancias sea precedida. Este proceso es el mismo que Python que le pregunta a una clase qué hacer al llamar a __getattr__ cuando hace referencia a uno de sus atributos al hacer myclass.attribute .

Una metaclase esencialmente decide lo que significa la definición de una clase y cómo implementar esa definición. Véase, por ejemplo, http://code.activestate.com/recipes/498149/ , que esencialmente recrea las struct estilo C en Python utilizando metaclases. El hilo ¿Cuáles son sus casos de uso (concretos) para metaclases en Python? También proporciona algunos ejemplos, en general, parecen estar relacionados con la progtwigción declarativa, especialmente como se usa en los ORM.

En esta situación, si usa su Método # 2 y una subclase define un método __new__ , se ejecutará cada vez que llame a SubClassOfSingleton() , porque es responsable de llamar al método que devuelve la instancia almacenada. Con una metaclase, solo se llamará una vez , cuando se cree la única instancia. Desea personalizar lo que significa llamar a la clase , que se decide por su tipo.

En general, tiene sentido usar una metaclase para implementar un singleton. Un singleton es especial porque se crea solo una vez , y una metaclase es la forma en que se personaliza la creación de una clase . El uso de una metaclase le da más control en caso de que necesite personalizar las definiciones de clase singleton de otras maneras.

Sus singletons no necesitarán herencia múltiple (ya que la metaclase no es una clase base), pero para las subclases de la clase creada que usan herencia múltiple, debe asegurarse de que la clase singleton sea la primera / izquierda con una metaclase que redefine __call__ Es muy poco probable que esto sea un problema. El dictado de la instancia no está en el espacio de nombres de la instancia, por lo que no se sobrescribirá accidentalmente.

También escuchará que el patrón de singleton viola el “Principio de Responsabilidad Única”, cada clase debe hacer solo una cosa . De esa manera, no tiene que preocuparse por arruinar una cosa que hace el código si necesita cambiar otra, porque están separadas y encapsuladas. La implementación de metaclase pasa esta prueba . La metaclase es responsable de imponer el patrón y la clase y las subclases creadas no deben ser conscientes de que son singletons . El método # 1 falla esta prueba, como anotó con “MyClass en sí misma es una función, no una clase, por lo que no puede llamar métodos de clase desde ella”.

Versión compatible con Python 2 y 3

Escribir algo que funcione en Python2 y 3 requiere usar un esquema un poco más complicado. Dado que las metaclases suelen ser subclases de tipo de type , es posible usar una para crear dinámicamente una clase base intermediaria en tiempo de ejecución con ella como su metaclase y luego usarla como la clase base de la clase base pública Singleton . Es más difícil de explicar que de hacer, como se ilustra a continuación:

 # 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 

Un aspecto irónico de este enfoque es que utiliza subclases para implementar una metaclase. Una posible ventaja es que, a diferencia de una metaclase pura, isinstance(inst, Singleton) devolverá True .

Correcciones

En otro tema, probablemente ya haya notado esto, pero la implementación de la clase base en su publicación original es incorrecta. _instances deben ser referenciadas en la clase , debes usar super() o estás recurriendo , y __new__ es en realidad un método estático al que debes pasar la clase , no un método de clase, ya que la clase real no tiene Se ha creado aún cuando se llama. Todas estas cosas también serán ciertas para una implementación de metaclase.

 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() 

Decorador regresando una clase

Originalmente estaba escribiendo un comentario pero era demasiado largo, así que lo agregaré aquí. El método # 4 es mejor que la otra versión de decorador, pero es más código del necesario para un singleton, y no es tan claro lo que hace.

Los principales problemas provienen de la clase es su propia clase base. Primero, ¿no es extraño que una clase sea una subclase de una clase casi idéntica con el mismo nombre que existe solo en su atributo __class__ ? Esto también significa que no puede definir ningún método que llame al método del mismo nombre en su clase base con super() porque recursionarán. Esto significa que su clase no puede personalizar __new__ , y no puede derivar de ninguna clase que necesite __init__ llamada.

Cuando usar el patrón singleton

Su caso de uso es uno de los mejores ejemplos de querer usar un singleton. Dice en uno de los comentarios “Para mí, el registro siempre ha sido un candidato natural para Singletons”. Tienes toda la razón .

Cuando la gente dice que los singletons son malos, la razón más común es que son estados compartidos implícitos . Mientras que las variables globales y las importaciones de módulos de nivel superior son estados compartidos explícitos , generalmente se crea una instancia de otros objetos que se transmiten. Este es un buen punto, con dos excepciones .

El primero, y uno que se menciona en varios lugares, es cuando los singletons son constantes . El uso de constantes globales, especialmente las enumeraciones, se acepta ampliamente y se considera sensato, ya que no importa qué, ninguno de los usuarios puede desordenarlos por ningún otro usuario . Esto es igualmente cierto para un singleton constante.

La segunda excepción, que se menciona menos, es la opuesta: cuando el singleton es solo un receptor de datos , no una fuente de datos (directa o indirectamente). Esta es la razón por la que los madereros se sienten como un uso “natural” para singletons. Como los diferentes usuarios no están cambiando los registradores de manera que otros usuarios se preocupen, realmente no hay estado compartido . Esto niega el argumento principal en contra del patrón de singleton, y los convierte en una opción razonable debido a su facilidad de uso para la tarea.

Aquí hay una cita de http://googletesting.blogspot.com/2008/08/root-cause-of-singletons.html :

Ahora, hay un tipo de Singleton que está bien. Ese es un singleton donde todos los objetos alcanzables son inmutables. Si todos los objetos son inmutables, Singleton no tiene un estado global, ya que todo es constante. Pero es tan fácil convertir este tipo de singleton en uno mutable, es una pendiente muy resbaladiza. Por lo tanto, yo también estoy en contra de estos Singletons, no porque sean malos, sino porque es muy fácil que se vuelvan malos. (Como nota al margen, la enumeración de Java son solo este tipo de singletons. Mientras no ponga un estado en su enumeración, está bien, así que no lo haga).

El otro tipo de Singletons, que son semi aceptables, son aquellos que no afectan la ejecución de su código, no tienen “efectos secundarios”. El registro es un ejemplo perfecto. Se carga con Singletons y estado global. Es aceptable (ya que no le hará daño) porque su aplicación no se comporta de manera diferente, ya sea que un registrador dado esté habilitado o no. La información aquí fluye de una manera: desde su aplicación al registrador. Incluso los registradores de pensamiento son un estado global, ya que no se transfiere información de los registradores a su aplicación, los registradores son aceptables. Aún debe inyectar su registrador si desea que su prueba afirme que algo se está registrando, pero en general los registradores no son perjudiciales a pesar de estar llenos de estado.

 class Foo(object): pass some_global_variable = Foo() 

Los módulos se importan solo una vez, todo lo demás se está pensando demasiado. No uses singletons y trata de no usar globales.

Usa un módulo. Se importa solo una vez. Defina algunas variables globales en él, serán los ‘atributos’ de singleton. Agregue algunas funciones – los ‘métodos’ del singleton.

Probablemente nunca necesites un singleton en Python. Simplemente defina todos sus datos y funciones en un módulo y tendrá un singleton de facto.

Si realmente tienes que tener una clase de singleton, me gustaría ir con:

 class My_Singleton(object): def foo(self): pass my_singleton = My_Singleton() 

Usar:

 from mysingleton import my_singleton my_singleton.foo() 

donde mysingleton.py es su nombre de archivo en el que se define My_Singleton. Esto funciona porque después de la primera importación de un archivo, Python no vuelve a ejecutar el código.

Aquí hay una frase para usted:

 singleton = lambda c: c() 

Así es como lo usas:

 @singleton class wat(object): def __init__(self): self.x = 1 def get_x(self): return self.x assert wat.get_x() == 1 

Su objeto se instancia con entusiasmo. Esto puede o no ser lo que quieres.

Consulta la pregunta sobre el desbordamiento de stack ¿Existe una forma simple y elegante de definir singletons en Python? Con varias soluciones.

Recomiendo encarecidamente ver las charlas de Alex Martelli sobre patrones de diseño en python: parte 1 y parte 2 . En particular, en la parte 1 él habla de singletons / objetos de estado compartidos.

Aquí está mi propia implementación de singletons. Todo lo que tienes que hacer es decorar la clase; para obtener el singleton, entonces tienes que usar el método de Instance . Aquí hay un ejemplo:

  @Singleton class Foo: def __init__(self): print 'Foo created' f = Foo() # Error, this isn't how you get the instance of a singleton f = Foo.Instance() # Good. Being explicit is in line with the Python Zen g = Foo.Instance() # Returns already created instance print f is g # True 

Y aquí está el código:

 class Singleton: """ A non-thread-safe helper class to ease implementing singletons. This should be used as a decorator -- not a metaclass -- to the class that should be a singleton. The decorated class can define one `__init__` function that takes only the `self` argument. Other than that, there are no restrictions that apply to the decorated class. To get the singleton instance, use the `Instance` method. Trying to use `__call__` will result in a `TypeError` being raised. Limitations: The decorated class cannot be inherited from. """ def __init__(self, decorated): self._decorated = decorated def Instance(self): """ Returns the singleton instance. Upon its first call, it creates a new instance of the decorated class and calls its `__init__` method. On all subsequent calls, the already created instance is returned. """ try: return self._instance except AttributeError: self._instance = self._decorated() return self._instance def __call__(self): raise TypeError('Singletons must be accessed through `Instance()`.') def __instancecheck__(self, inst): return isinstance(inst, self._decorated) 

El método 3 parece ser muy bueno, pero si quieres que tu progtwig se ejecute tanto en Python 2 como en Python 3 , no funciona. Incluso la protección de las variantes separadas con las pruebas para la versión de Python falla, porque la versión de Python 3 da un error de syntax en Python 2.

Gracias a Mike Watkins: http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/ . Si desea que el progtwig funcione tanto en Python 2 como en Python 3, necesita hacer algo como:

 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] MC = Singleton('MC', (object), {}) class MyClass(MC): pass # Code for the class implementation 

Supongo que el ‘objeto’ en la asignación debe reemplazarse con el ‘BaseClass’, pero no lo he intentado (he intentado el código como se ilustra).

Bueno, aparte de estar de acuerdo con la sugerencia general de Pythonic sobre tener un nivel de módulo global, ¿qué tal esto?

 def singleton(class_): class class_w(class_): _instance = None def __new__(class2, *args, **kwargs): if class_w._instance is None: class_w._instance = super(class_w, class2).__new__(class2, *args, **kwargs) class_w._instance._sealed = False return class_w._instance def __init__(self, *args, **kwargs): if self._sealed: return super(class_w, self).__init__(*args, **kwargs) self._sealed = True class_w.__name__ = class_.__name__ return class_w @singleton class MyClass(object): def __init__(self, text): print text @classmethod def name(class_): print class_.__name__ x = MyClass(111) x.name() y = MyClass(222) print id(x) == id(y) 

La salida es:

 111 # the __init__ is called only on the 1st time MyClass # the __name__ is preserved True # this is actually the same instance 

Qué tal esto:

 def singleton(cls): instance=cls() cls.__new__ = cls.__call__= lambda cls: instance cls.__init__ = lambda self: None return instance 

Úsalo como decorador en una clase que debería ser un singleton. Me gusta esto:

 @singleton class MySingleton: #.... 

Esto es similar al decorador singleton = lambda c: c() en otra respuesta. Al igual que la otra solución, la única instancia tiene el nombre de la clase ( MySingleton ). Sin embargo, con esta solución aún puede “crear” instancias (en realidad obtener la única instancia) de la clase, haciendo MySingleton() . También le impide crear instancias adicionales al hacer type(MySingleton)() (que también devuelve la misma instancia).

Las respuestas anteriores son correctas, pero no estoy de acuerdo con la statement que se publicó como parte de la pregunta en el Método 1 “MyClass en sí misma es una función, no una clase, por lo que no puede llamar a los métodos de clase”. Vea mi ejemplo a continuación que el método se llama varias veces, en MyClass que está decorado con una etiqueta singleton.

Además, tenga en cuenta que esto es muy similar a algunas de las respuestas publicadas y se basa en el documento de Python, pero es ligeramente diferente porque la clase y la función están diseñadas de manera que pueden recibir 1 o 0 argumentos y aún así funciona de forma única.

introduzca la descripción de la imagen aquí Aquí está la prueba de que puede llamar a los métodos de singleton varias veces y muestra que una instancia de la clase todavía se usa y no se crean nuevos objetos.

 #/usr/bin/env python def singleton(cls): instances = {} def getinstance(anyArgs=None): if cls not in instances: instances[cls] = cls(anyArgs) return instances[cls] return getinstance @singleton class MyClass: def __init__(self,count=None): print("print argument if any exists",count) def test(self, counter): # time.sleep(1000) print("-->",counter) return counter ### create two objects to see if we get a singleton behavior ! a = MyClass(10000) a.test(1) b = MyClass() b.test(2) if a != b: print("this is not a singleton") #lets makesure it's still is the same object if a!=b: print("error") 

Dado que theheadofabroom (la persona que publicó la pregunta) había dado algunos comentarios sobre su pregunta original, fui y trabajé en una nueva solución basada en sus comentarios (aún conservé mi respuesta anterior porque creo que podría ser útil para algunos, aunque es no es exactamente lo que el jefe de familia está preguntando). Aquí está la respuesta actualizada:

introduzca la descripción de la imagen aquí

Aquí está el código para copiarlo y pegarlo 🙂

 #/usr/bin/env python from functools import wraps def singleton(cls): instances = {} def getinstance(anyArgs=None): if cls not in instances: instances[cls] = cls(anyArgs) return instances[cls] return getinstance def add_function(cls): def outer_decorate_it(somefunction): @wraps(somefunction) def wrapper( *args, **kwargs): return somefunction(*args, **kwargs) setattr(cls, somefunction.__name__, wrapper) return somefunction return outer_decorate_it @singleton class MyClass(): def __init__(self,count=None): print("print argument if any exists",count) @add_function(MyClass) def testit(): print("It's me the function from the class") MyClass.testit() 

Code based on Tolli’s answer .

 #decorator, modyfies new_cls def _singleton(new_cls): instance = new_cls() #2 def new(cls): if isinstance(instance, cls): #4 return instance else: raise TypeError("I can only return instance of {}, caller wanted {}".format(new_cls, cls)) new_cls.__new__ = new #3 new_cls.__init__ = lambda self: None #5 return new_cls #decorator, creates new class def singleton(cls): new_cls = type('singleton({})'.format(cls.__name__), (cls,), {} ) #1 return _singleton(new_cls) #metaclass def meta_singleton(name, bases, attrs): new_cls = type(name, bases, attrs) #1 return _singleton(new_cls) 

Explicación:

  1. Create new class, inheriting from given cls
    (it doesn’t modify cls in case someone wants for example singleton(list) )

  2. Create instance. Before overriding __new__ it’s so easy.

  3. Now, when we have easily created instance, overrides __new__ using method defined moment ago.
  4. The function returns instance only when it’s what the caller expects, otherwise raises TypeError .
    The condition is not met when someone attempts to inherit from decorated class.

  5. 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__() .

    instance is already initialized, so function replaces __init__ with function doing nothing.

See it working online

It is slightly similar to the answer by fab but not exactly the same.

The singleton contract does not require that we be able to call the constructor multiple times. As a singleton should be created once and once only, shouldn’t it be seen to be created just once? “Spoofing” the constructor arguably impairs legibility.

So my suggestion is just this:

 class Elvis(): def __init__(self): if hasattr(self.__class__, 'instance'): raise Exception() self.__class__.instance = self # initialisation code... @staticmethod def the(): if hasattr(Elvis, 'instance'): return Elvis.instance return Elvis() 

This does not rule out the use of the constructor or the field instance by user code:

 if Elvis() is King.instance: 

… if you know for sure that Elvis has not yet been created, and that King has.

But it encourages users to use the the method universally:

 Elvis.the().leave(Building.the()) 

To make this complete you could also override __delattr__() to raise an Exception if an attempt is made to delete instance , and override __del__() so that it raises an Exception (unless we know the program is ending…)

Further improvements


My thanks to those who have helped with comments and edits, of which more are welcome. While I use Jython, this should work more generally, and be thread-safe.

 try: # This is jython-specific from synchronize import make_synchronized except ImportError: # This should work across different python implementations def make_synchronized(func): import threading func.__lock__ = threading.Lock() def synced_func(*args, **kws): with func.__lock__: return func(*args, **kws) return synced_func class Elvis(object): # NB must be subclass of object to use __new__ instance = None @classmethod @make_synchronized def __new__(cls, *args, **kwargs): if cls.instance is not None: raise Exception() cls.instance = object.__new__(cls, *args, **kwargs) return cls.instance def __init__(self): pass # initialisation code... @classmethod @make_synchronized def the(cls): if cls.instance is not None: return cls.instance return cls() 

Points of note:

  1. If you don’t subclass from object in python2.x you will get an old-style class, which does not use __new__
  2. When decorating __new__ you must decorate with @classmethod or __new__ will be an unbound instance method
  3. This could possibly be improved by way of use of a metaclass, as this would allow you to make the a class-level property, possibly renaming it to instance

I’ll toss mine into the ring. It’s a simple decorator.

 from abc import ABC def singleton(real_cls): class SingletonFactory(ABC): instance = None def __new__(cls, *args, **kwargs): if not cls.instance: cls.instance = real_cls(*args, **kwargs) return cls.instance SingletonFactory.register(real_cls) return SingletonFactory # Usage @singleton class YourClass: ... # Your normal implementation, no special requirements. 

Benefits I think it has over some of the other solutions:

  • It’s clear and concise (to my eye ;D).
  • Its action is completely encapsulated. You don’t need to change a single thing about the implementation of YourClass . This includes not needing to use a metaclass for your class (note that the metaclass above is on the factory, not the “real” class).
  • It doesn’t rely on monkey-patching anything.
  • It’s transparent to callers:
    • Callers still simply import YourClass , it looks like a class (because it is), and they use it normally. No need to adapt callers to a factory function.
    • What YourClass() instantiates is still a true instance of the YourClass you implemented, not a proxy of any kind, so no chance of side effects resulting from that.
    • isinstance(instance, YourClass) and similar operations still work as expected (though this bit does require abc so precludes Python <2.6).

One downside does occur to me: classmethods and staticmethods of the real class are not transparently callable via the factory class hiding it. I’ve used this rarely enough that I’ve never happen to run into that need, but it would be easily rectified by using a custom metaclass on the factory that implements __getattr__() to delegate all-ish attribute access to the real class.

A related pattern I’ve actually found more useful (not that I’m saying these kinds of things are required very often at all) is a “Unique” pattern where instantiating the class with the same arguments results in getting back the same instance. Ie a “singleton per arguments”. The above adapts to this well and becomes even more concise:

 def unique(real_cls): class UniqueFactory(ABC): @functools.lru_cache(None) # Handy for 3.2+, but use any memoization decorator you like def __new__(cls, *args, **kwargs): return real_cls(*args, **kwargs) UniqueFactory.register(real_cls) return UniqueFactory 

All that said, I do agree with the general advice that if you think you need one of these things, you really should probably stop for a moment and ask yourself if you really do. 99% of the time, YAGNI.

One liner (I am not proud, but it does the job):

 class Myclass: def __init__(self): # do your stuff globals()[type(self).__name__] = lambda: self # singletonify 

If you don’t need lazy initialization of the instance of the Singleton, then the following should be easy and thread-safe:

 class A: instance = None # Methods and variables of the class/object A follow A.instance = A() 

This way A is a singleton initialized at module import.

I can’t remember where I found this solution, but I find it to be the most ‘elegant’ from my non-Python-expert point of view:

 class SomeSingleton(dict): __instance__ = None def __new__(cls, *args,**kwargs): if SomeSingleton.__instance__ is None: SomeSingleton.__instance__ = dict.__new__(cls) return SomeSingleton.__instance__ def __init__(self): pass def some_func(self,arg): pass 

Why do I like this? No decorators, no meta classes, no multiple inheritance…and if you decide you don’t want it to be a Singleton anymore, just delete the __new__ method. As I am new to Python (and OOP in general) I expect someone will set me straight about why this is a terrible approach?

This is my preferred way of implementing singletons:

 class Test(object): obj = None def __init__(self): if Test.obj is not None: raise Exception('A Test Singleton instance already exists') # Initialization code here @classmethod def get_instance(cls): if cls.obj is None: cls.obj = Test() return cls.obj @classmethod def custom_method(cls): obj = cls.get_instance() # Custom Code here 

This answer is likely not what you’re looking for. I wanted a singleton in the sense that only that object had its identity, for comparison to. In my case it was being used as a Sentinel Value . To which the answer is very simple, make any object mything = object() and by python’s nature, only that thing will have its identity.

 #!python MyNone = object() # The singleton for item in my_list: if item is MyNone: # An Example identity comparison raise StopIteration 

This solution causes some namespace pollution at the module level (three definitions rather than just one), but I find it easy to follow.

I’d like to be able to write something like this (lazy initialization), but unfortunately classes are not available in the body of their own definitions.

 # wouldn't it be nice if we could do this? class Foo(object): instance = None def __new__(cls): if cls.instance is None: cls.instance = object() cls.instance.__class__ = Foo return cls.instance 

Since that isn’t possible, we can break out the initialization and the static instance in

Eager Initialization:

 import random class FooMaker(object): def __init__(self, *args): self._count = random.random() self._args = args class Foo(object): def __new__(self): return foo_instance foo_instance = FooMaker() foo_instance.__class__ = Foo 

Lazy initialization:

Eager Initialization:

 import random class FooMaker(object): def __init__(self, *args): self._count = random.random() self._args = args class Foo(object): def __new__(self): global foo_instance if foo_instance is None: foo_instance = FooMaker() return foo_instance foo_instance = None