1 首先网上有很多实现方式,而且stackflow里面有大神详细介绍了各种实现。自己google吧,就不贴URL了。
我这里简述原理,放个简单demo帮助理解。
1 class Singleton(type): 2 def __init__(self, name, bases, dic): 3 print ".... Singleton.init ...." 4 super(Singleton, self).__init__(name, bases, dic) 5 self.instance = None 6 7 def __call__(self, *args, **kwargs): 8 print ".... Singleton.call ...." 9 if self.instance is None: 10 self.instance = super(Singleton, self).__call__(*args, **kwargs) 11 return self.instance 12 13 print "====================== 1 =======================" 14 class test: 15 __metaclass__ = Singleton #call Singleton.__init__ 16 def __init__(self): 17 print "test.init ..." 18 def __call__(self): 19 print "test.call ..." 20 21 class test2: 22 __metaclass__ = Singleton #call Singleton.__init__ 23 def __init__(self): 24 print "test2.init ..." 25 def __call__(self): 26 print "test2.call ..." 27 28 print "====================== 2 =======================" 29 a = test() #call Singleton.__call__ 30 b = test2() #call sSngleton.__call__ 31 32 print "====================== 3 =======================" 33 a1 = test() 34 b1 = test2() 35 print id(a),id(a1),id(b),id(b1) 36 print "====================== 4 =======================" 37 a1() 38 b1() 39 40 print "====================== 5 =======================" 41 a.c = 100 42 b.c = 111 43 print a1.c 44 print b1.c
输出结果:
1 bash-3.2$ python test.py 2 ====================== 1 ======================= 3 .... Singleton.init .... 4 .... Singleton.init .... 5 ====================== 2 ======================= 6 .... Singleton.call .... 7 test.init ... 8 .... Singleton.call .... 9 test2.init ... 10 ====================== 3 ======================= 11 .... Singleton.call .... 12 .... Singleton.call .... 13 4476624848 4476624848 4476670096 4476670096 14 ====================== 4 ======================= 15 test.call ... 16 test2.call ... 17 ====================== 5 ======================= 18 100 19 111
demo中建了2个单例类,test,test2。都是通过__metaclass__ = Singleton的方式。
测试结果:
通过测试输出可以看出,id(a) = id(a1),id(b)=id(b1); 而且创建一个c attribute给a,a1同时也会得到一个一模一样的c,包括c的值。 说明单例OK。
原理:
这里单例是用__metaclass__方式实现。__metaclass__的意思就是class的class。
所以一旦设定test和test2的__metaclass__ == Singleton,就会利用Singleton类的实例来作为test,test2的类。(稍微有点拗口)
请注意line 14和line 22,这2个地方对应输出结果里面line 2,line3的打印。说明:我们一旦设定test,test2的__metaclass__ = Singleton了,Singleton就立刻__init__ ,而且对于每个单例类(这里的test或test2)只在定义的时候做一次。
后面我们实例话test,test2的时候:a = test(),b=test2();则系统会调用Singleton的__call__;实例化几次test,test2,就调用几次Singleton的__call__ 。 所以,我们只要在Singleton的__call__里面做单例的实现即可。
具体实现方式很简单,看源码即可。
补充一下:
test类的__init__ 函数对应 a=test()调用
__call__函数对应 a()