Python 单例 / 对象实例化
我正在学习Python,最近尝试实现一个单例类作为练习。我的代码如下:
_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__']
我想做的事情有可能实现吗?如果不行,还有其他方法可以做到吗?
欢迎任何建议。
谢谢。
5 个回答
4
来自 单例模式 (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()
6
这是一个关于设计模式的讨论,提到了Bruce Eckel的代码片段。提问者对这个代码是怎么工作的感到困惑。
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>
'''
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(也叫单态模式)要比你选择的单例模式(Highlander)要好得多,但这和你问的问题是不同的事情;-)。