Creando un singleton en Python

sta pregunta no es para la discusión de si laatrón de diseño @singleton es deseable, es un antipatrón, o para cualquier guerra religiosa, pero para discutir cómo este patrón se implementa mejor en Python de la manera más pitónica. En este caso, defino 'más pitónico' para significar que sigue el 'principio del menor 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 añadido 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

os decoradores son aditivos de una manera que a menudo es más intuitiva que la herencia múltipl

Contra

Mientras que los objetos creados con MyClass () serían verdaderos objetos únicos, MyClass en sí es una función, no una clase, por lo que no puede llamar a los métodos de clase desde ella. También porm = MyClass(); n = MyClass(); o = type(n)(); luegom == n && m != o && n != oé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

Contra

Herencia múltiple: ¡eugh! @__new__ podría sobrescribirse durante la herencia de una segunda clase base? Uno tiene que pensar más de lo necesario. Método 3: A 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 herenciaUsos__metaclass__ para su propio propósito (y me hizo consciente de ello)

Contra

¿Hay alguno? Método 4: decorador que devuelve 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

Contra

¿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 de la_sealed atributo No se pueden llamar métodos del mismo nombre en clases base usandosuper() porque recurrirán. Esto significa que no puedes personalizar__new__ y no puede subclasificar una clase que necesita que llame a__init__.

Respuestas a la pregunta(15)

Su respuesta a la pregunta