我试图用Python实现一个单例,在阅读了这个职位之后,我发现自己比以前更加困惑了。答案太多了,他们中的许多人已经获得了相当多的选票。现在的问题可能不是我有一个单例,而是状态只能初始化一次这一事实。我尝试了几个实现SingletonA和SingletonB,但我无法管理它的工作。对于我真正的问题,__init__函数很重,所以我只需要做一次。到目前为止,这就是我所拥有的:
class ClassA:
def __init__(self):
# some state
print("Creating state in A")
self.X = 1.
self.Y = 2.
class SingletonA(ClassA):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(SingletonA, cls).__new__(
cls, *args, **kwargs)
return cls._instance
class ClassB:
__shared_state = {}
def __init__(self):
if not bool(ClassB.__shared_state):
# some state
print("Creating state in B")
self.X = 1.
self.Y = 2.
self.__dict__ = self.__shared_state
def singleton(cls):
obj = cls()
# Always return the same object
cls.__new__ = staticmethod(lambda cls: obj)
# Disable __init__
try:
del cls.__init__
except AttributeError:
pass
return cls
@singleton
class SingletonB(ClassB):
pass
if __name__ == "__main__":
a1 = SingletonA()
a2 = SingletonA()
if (id(a1) == id(a2)):
print("Same",a1.X, a1.Y)
else:
print("Different",a1.X, a1.Y)
b1 = SingletonB()
b2 = SingletonB()
if (id(b1) == id(b2)):
print("Same",b1.X, b1.Y)
else:
print("Different",b1.X, b1.Y)现在这是印刷:
$ python singleton.py
Creating state in B
Creating state in B
Same 1.0 2.0
Creating state in A
Creating state in A
Same 1.0 2.0指出事实上,我确实有一个单例类,但我希望避免状态的创建。
发布于 2015-10-20 19:12:32
这不能工作,因为__init__方法是在通过__new__创建对象之后调用的。Python语言引用提取液
如果
__new__()返回一个cls实例,那么将像调用__init__(self[, ...])一样调用新实例的__init__()方法,其中self是新实例,其余参数与传递给__new__()的参数相同。
相反,您应该有一个与__init__不同的特殊初始化方法,并调用_instance创建。
代码可以是(不需要父类,所以我省略了它):
class SingletonA:
_instance = None
def __init__(self):
# some state
print("Creating dummy state in SingletonA")
def _init(self):
# some state
print("Creating state in SingletonA")
self.X = 1.
self.Y = 2.
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super(SingletonA, cls).__new__(
cls, *args, **kwargs)
cls._instance._init()
return cls._instance但实际上,您只需在声明时构建实例:
class SingletonA:
def __init__(self):
# some state
print("Creating dummy state in SingletonA")
def _init(self):
# some state
print("Creating state in A")
self.X = 1.
self.Y = 2.
def __new__(cls, *args, **kwargs):
return cls._instance
SingletonA._instance = super(SingletonA, SingletonA).__new__(SingletonA)
SingletonA._instance._init()这两种方法都会导致以下输出(对于SingletonA部分):
Creating state in A
Creating dummy state in SingletonA
Creating dummy state in SingletonA
('Same', 1.0, 2.0)完全删除__init__方法将导致一次初始化。
注释版本可以是:
class ClassB:
def __init__(self):
# some state
print("Creating state in B")
self.X = 1.
self.Y = 2.
def singleton(cls):
obj = cls()
# Always return the same object
cls._instance = obj
cls.__new__ = staticmethod(lambda cls: cls._instance)
# Disable __init__
cls.__init__ = (lambda self: None)
return cls
@singleton
class SingletonB(ClassB):
pass简单地将单例实例存储在类本身中。
发布于 2015-10-20 18:49:32
如果我对你的理解正确,这就是你所需要的:
# edited according to discussion in comments
class C:
_shared_dict = None
def __init__(self):
if self._shared_dict is None:
print("initializing")
self.x = 1
self.y = 2
self.__class__._shared_dict = self.__dict__
else:
self.__dict__ = self._shared_dict
a=C()
b=C()
print(id(a), a.x, a.y)
print(id(b), b.x, b.y)所有实例都将共享相同的数据,该数据将只计算一次。
请注意,在读取时,您可以将共享数据引用为self._shared_dict,但在写入类属性self.__class__._shared_dict时必须使用它的全名。
https://stackoverflow.com/questions/33243454
复制相似问题