Sentido de Python / instanciación de objetos

Estoy aprendiendo Python y he estado tratando de implementar una clase de tipo Singleton como prueba. El código que tengo es el siguiente:

_Singleton__instance = None class Singleton: def __init__(self): global __instance if __instance == None: self.name = "The one" __instance = self else: self = __instance 

Esto funciona en parte, pero la parte self = __instance parece estar fallando. He incluido algunos resultados del interpretador para demostrar (el código anterior se guarda en singleton.py):

 >>> import singleton >>> x = singleton.Singleton() >>> x.name 'The one' >>> singleton._Singleton__instance.name 'The one' >>> y = singleton.Singleton() >>> y.name Traceback (most recent call last): File "", line 1, in  AttributeError: Singleton instance has no attribute 'name' >>> type(y)  >>> dir(y) ['__doc__', '__init__', '__module__'] 

¿Es posible hacer lo que estoy tratando? Si no hay otra forma de hacer esto?

Cualquier sugerencia de bienvenida.

Aclamaciones.

Asignar un argumento o cualquier otra variable local (nombre de barra) nunca puede tener CUALQUIER efecto fuera de la función; eso se aplica a su self = whatever que self = whatever que correspondería a CUALQUIER otra asignación a un argumento (nombre de barra) u otra variable local.

Más bien, anular __new__ :

 class Singleton(object): __instance = None def __new__(cls): if cls.__instance == None: cls.__instance = object.__new__(cls) cls.__instance.name = "The one" return cls.__instance 

He hecho otras mejoras aquí, como desarraigar la global, la clase de estilo antiguo, etc.

Mucho mejor es usar Borg (también conocido como monostato) en lugar de su Highlander (alias singleton) elegido, pero eso es un problema diferente al que está preguntando ;-).

Fragmento de código de Bruce Eckel de Design Pattern: Estoy confundido sobre cómo funciona

 class Borg: _shared_state = {} def __init__(self): self.__dict__ = self._shared_state class MySingleton(Borg): def __init__(self, arg): Borg.__init__(self) self.val = arg def __str__(self): return self.val x = MySingleton('sausage') print x y = MySingleton('eggs') print y z = MySingleton('spam') print z print x print y print ´x´ print ´y´ print ´z´ output = ''' sausage eggs spam spam spam <__main__. MySingleton instance at 0079EF2C> <__main__. MySingleton instance at 0079E10C> <__main__. MySingleton instance at 00798F9C> ''' 

Desde Singleton Pattern (Python) :

 class Singleton(type): def __init__(self, name, bases, dict): super(Singleton, self).__init__(name, bases, dict) self.instance = None def __call__(self, *args, **kw): if self.instance is None: self.instance = super(Singleton, self).__call__(*args, **kw) return self.instance class MyClass(object): __metaclass__ = Singleton print MyClass() print MyClass() 

Esto es sobre el Singleton más básico que puedes hacer. Utiliza un método de clase para verificar si el singleton ha sido creado y crea uno nuevo si no lo ha hecho. Hay formas más avanzadas de hacer esto, como anular el método __new__ .

 class Singleton: instance = None @classmethod def get(cls): if cls.instance is None: cls.instance = cls() return cls.instance def __init__(self): self.x = 5 # or whatever you want to do sing = Singleton.get() print sing.x # prints 5 

En cuanto a por qué su código falla, hay varias razones. En primer lugar, cuando se llama a __init__ , ya se ha creado un nuevo objeto, que __init__ el propósito del patrón de singleton. Segundo, cuando dices self = __instance , simplemente se restablece el self variable local; esto sería como decir

 def f(x): x = 7 # changes the value of our local variable y = 5 f(y) print y # this is still 5 

Como las variables en Python se pasan por valor y no por referencia, no puedes decir self = blah y hacer que sean significativas de la manera que deseas. La clase Singleton de arriba es más de lo que quieres, a menos que quieras ser elegante y considerar anular el operador __new__ .

 self = _instance 

Esto no hará lo que usted espera que haga. Lea acerca de cómo Python trata los nombres.