TN的人问到我怎么实现。我只大概记得是在一个类中定义一个指向为NULL的变量。然后去创建这个类的对象。如果这个对象为空,就新实例化该类的对象,否则就什么也不做。然后返回这个变量。他又问我怎么去传递引用。我一下子就不知道怎么说了(因为没写过)。这几天查了一下相关资料总算有了实际的概念。
在类中定义一个方法,这个方法去检查和实例化这个变量。但是有两点要注意。一是这个方法应该用类名去直接调用,所以要用@staicmethod声明为静态方法。第二点是要注意多线程的安全问题。所以可以用threading类的方法加锁。
#!/usr/bin/env python
#-*- coding: utf-8 -*-
"""
# Author: DMCC-DATA
# Created Time : Thu 17 Dec 2015 03:31:15 PM CST
# File Name: singleton.py
# Description:
"""
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import os,traceback,logging,multiprocessing,re
import threading
class Singleton():
instance = None
a = 1
mutex = threading.Lock()
def _init__(self):
print 'init self'
pass
@staticmethod
def GetInstance():
if(Singleton.instance==None):
Singleton.mutex.acquire()
if(Singleton.instance==None):
print 'init instance'
Singleton.instance=Singleton()
else:
print 'exist instance'
Singleton.mutex.release()
else:
print 'exist instance'
return Singleton.instance
def func():
Singleton.GetInstance()
Singleton.GetInstance()
Singleton.GetInstance()
pool = multiprocessing.Pool(5)
for i in range(10):
pool.apply_async(Singleton.GetInstance(),[])
pool.close()
pool.join()
if __name__ == '__main__':
func()
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
但是这个方法需要改动类本身,接下来有个更方便的方法
如果有一个方法,你想对它实现一些增强功能,但是又尽可能避免对它代码的改动,就可以把它当作切面,使用装饰器模式。
写一个包装方法,方法的参数是要装饰的方法和它的参数列表,在这个方法中写一个内嵌包装函数,把要增强的功能和原方法结合起来,这个内嵌函数调用原方法和参数并接收返回值,并返回这个值。然后包装方法返回这个内嵌函数。最后调用这个包装方法,把引用传给原方法。这一步可以使用语法糖@
1 #!/usr/bin/env python
2 #-*- coding: utf-8 -*-
3
4 """
5 # Author: DMCC-DATA
6 # Created Time : Thu 17 Dec 2015 05:14:42 PM CST
7 # File Name: decorator.py
8 # Description:
9 """
10
11 import sys
12 reload(sys)
13 sys.setdefaultencoding('utf8')
14
15 import os,traceback,logging,multiprocessing,re
16
17 def deco(func):
18 def dec(*args):
19 print 111
20 res = func(*args)
21 print 222
22 return res
23 return dec
24
25 @deco
26 def add(a,b):
27 return a+b
28
29 def func2():
30 r = add(3,4)
31 print r
32
33 if __name__ == '__main__':
34 func2()
实际应用类中的代码
#!/usr/bin/env python
#-*- coding: utf-8 -*-
"""
# Author: DMCC-DATA
# Created Time : Fri 18 Dec 2015 09:37:46 AM CST
# File Name: decsingleton.py
# Description:
"""
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import os,traceback,logging,multiprocessing,re
import time
def singleton(cls):
instance = {}
def getinstance(*args):
if cls not in instance:
instance[cls] = cls(*args)
return instance[cls]
return getinstance
@singleton
# Person() = singleton(Pserson())
#(object) 声明继承自object,是一个新类,这里没实际作用
class Person(object):
def __init__(self):
self.t = self.gettime()
print self.t
def gettime(self):
t = time.time()
return t
def func():
p1 = Person()
p2 = Person()
print p1,p1.t
print p2,p2.t
p1.t = 1
print p1,p1.t
print p2,p2.t
if __name__ == '__main__':
func()
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
除此之外,还可以利用Python的__metaclass__和__dic__分别实现。后者又可以称作重写new方法,但是只是把所有实例对象共享属性,每次产生一个新对象。算作伪单例吧。
__metaclass__元类方法代码:
#!/usr/bin/env python
#-*- coding: utf-8 -*-
"""
# Author: DMCC-DATA
# Created Time : Thu 17 Dec 2015 03:31:15 PM CST
# File Name: singleton.py
# Description:
"""
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import os,traceback,logging,multiprocessing,re,time
import threading
class Singleton(type):
<span style="white-space:pre"> </span>def __init__(cls,name,bases,dict):
<span style="white-space:pre"> </span>super(Singleton,cls).__init__(name,bases,dict)
<span style="white-space:pre"> </span>cls.instance = None
<span style="white-space:pre"> </span>def __call__(cls,*args,**kw):
<span style="white-space:pre"> </span>if cls.instance is None:
<span style="white-space:pre"> </span>cls.instance = super(Singleton,cls).__call__(*args,**kw)
<span style="white-space:pre"> </span>return cls.instance
class SingletonCls(object):
<span style="white-space:pre"> </span>a = 1
<span style="white-space:pre"> </span>__metaclass__ = Singleton
<span style="white-space:pre"> </span>def __init__(self):
<span style="white-space:pre"> </span>self.t = self.gettime()
<span style="white-space:pre"> </span>print self.t
<span style="white-space:pre"> </span>def gettime(self):
<span style="white-space:pre"> </span>t = time.time()
<span style="white-space:pre"> </span>return t
def func():
<span style="white-space:pre"> </span>a1 = SingletonCls()
<span style="white-space:pre"> </span>a2 = SingletonCls()
<span style="white-space:pre"> </span>print a1,a1.a
<span style="white-space:pre"> </span>print a2,a2.a
<span style="white-space:pre"> </span>a1.a = 2
<span style="white-space:pre"> </span>a1.x = 999
<span style="white-space:pre"> </span>print a1,a1.a,a1.x
<span style="white-space:pre"> </span>print a2,a2.a,a2.x
<span style="white-space:pre"> </span>
if __name__ == '__main__':
<span style="white-space:pre"> </span>func()
共享属性方法代码:
#!/usr/bin/env python
#-*- coding: utf-8 -*-
"""
# Author: DMCC-DATA
# Created Time : Thu 17 Dec 2015 03:31:15 PM CST
# File Name: singleton.py
# Description:
"""
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import os,traceback,logging,multiprocessing,re,time
import threading
class Borg(object):
<span style="white-space:pre"> </span>_state = {}
<span style="white-space:pre"> </span>def __new__(cls,*args,**kw):
<span style="white-space:pre"> </span>ob = super(Borg,cls).__new__(cls,*args,**kw)
<span style="white-space:pre"> </span>ob.__dict__ = cls._state
<span style="white-space:pre"> </span>print 'init'
<span style="white-space:pre"> </span>return ob
class SingletonCls(Borg):
<span style="white-space:pre"> </span>a = 1
<span style="white-space:pre"> </span>def __init__(self):
<span style="white-space:pre"> </span>self.t = self.gettime()
<span style="white-space:pre"> </span>print self.t
<span style="white-space:pre"> </span>def gettime(self):
<span style="white-space:pre"> </span>t = time.time()
<span style="white-space:pre"> </span>return t
def func():
<span style="white-space:pre"> </span>a1 = SingletonCls()
<span style="white-space:pre"> </span>a2 = SingletonCls()
<span style="white-space:pre"> </span>print a1,a1.a
<span style="white-space:pre"> </span>print a2,a2.a
<span style="white-space:pre"> </span>a1.a = 2
<span style="white-space:pre"> </span>a1.x = 999
<span style="white-space:pre"> </span>print a1,a1.a,a1.x
<span style="white-space:pre"> </span>print a2,a2.a,a2.x
if __name__ == '__main__':
<span style="white-space:pre"> </span>func()
综上,在python实现单例模式有4种方法,前三种只实例化一个对象,最后一种实例化许多个相同属性的对象。其中第一个又要改写类本身。所以真正实用的就是装饰器法和元类法了。最喜欢的当然还是装饰器啦