问题复现
今天复习单例模式时,当用基于__new__
方法实现时,遇到过小问题。
代码如下:
from threading import Lock
class Signleton(object):
_signleton_lock = Lock()
def __init__(self, a, curr='a'):
self.a = a
self.curr = curr
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
with Signleton._signleton_lock:
if not hasattr(cls, '_instance'):
cls._instance = object.__new__(cls)
return cls._instance
def prove(self):
print('id = %d, a = %d, curr = %s' % (id(self), self.a, self.curr))
if __name__ == '__main__':
t1 = Signleton(2, 'b')
t2 = Signleton(7, 'c')
print(t1.prove() == t2.prove())
运行结果:
id = 140094976669456, a = 7, curr = c
id = 140094976669456, a = 7, curr = c
True
可以看到这个方法确实实现了单例模式。
但有个问题,实例的属性被修改为最后一次实例化时传入的参数了。
一开始有点不理解。直接上手调试了一下,才晓得问题出在哪。
问题解释
python
中实例化对象时,需要两步走。
- 调用
__new__
方法,返回一个对象 - 调用
__init__
方法, 对上一步返回的对象进行初始化
而我刚刚实现单例模式的方法只是修改了__new__
方法,使其每次都返回同一个对象。
但是没有处理__init__
方法,这就使得每次实例化对象时,都要运行一次__init__
方法。
这可不就会每次都把对象的属性修改为最后一次实例化的参数了嘛。