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()