我正在学习Python,并且我一直在尝试将Singleton类型作为测试来实现。我的代码如下:
_Singleton__instance = None
class Singleton:
def __init__(self):
global __instance
if __instance == None:
self.name = "The one"
__instance = self
else:
self = __instance
这部分有效,但self = __instance部分似乎失败了。我已经包含了解释器的一些输出来演示(上面的代码保存在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 "<stdin>", line 1, in <module>
AttributeError: Singleton instance has no attribute 'name'
>>> type(y)
<type 'instance'>
>>> dir(y)
['__doc__', '__init__', '__module__']
有可能做我正在尝试的事情吗?如果没有,还有另一种方法吗?
欢迎任何建议。
干杯。
答案 0 :(得分:22)
分配给参数或任何其他局部变量(裸名)不可能在函数外部产生任何影响;这适用于您的self = whatever
,因为它适用于(裸名)参数或其他局部变量的任何其他赋值。
相反,覆盖__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
我在这里做过其他改进,例如拔除全局类,旧式类等。
更好的是使用Borg(又名monostate)而不是你选择的汉兰达(又名单身人士),但这与你所询问的问题不同; - )。
答案 1 :(得分:6)
Bruce Eckel's code snippet from Design Pattern: I'm confused on how it works
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>
'''
答案 2 :(得分:4)
来自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()
答案 3 :(得分:3)
这是关于你可以制作的最基本的单身人士。它使用class method来检查单例是否已创建,如果没有,则创建一个新单例。有更多高级方法可以解决此问题,例如覆盖__new__
method。
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
至于你的代码失败的原因,有几个原因。首先,在调用__init__
时,已经创建了一个新对象,从而破坏了单例模式的目的。其次,当你说self = __instance
时,它只会重置局部变量self;这类似于说
def f(x):
x = 7 # changes the value of our local variable
y = 5
f(y)
print y # this is still 5
由于Python中的变量是按值而不是引用传递的,因此您不能说self = blah
并且以您想要的方式使其有意义。上面的Singleton类更符合您的要求,除非您想要了解并考虑覆盖__new__
运算符。
答案 4 :(得分:0)
self = _instance
这不会做你期望它做的事情。阅读Python如何处理名称。