VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • Python创建单例模式的5种方法(2)

 

在上面,我们定义了一个装饰器 singleton,它返回了一个内部函数 getinstance,该函数会判断某个类是否在字典 instances 中,如果不存在,则会将 cls 作为 key,cls(*args, **kw) 作为 value 存到 instances 中,否则,直接返回 instances[cls]。

方法3:使用元类(metaclass)

当你编写一个类的时候,某种机制会使用类名字,基类元组,类字典来创建一个类对象。新型类中这种机制默认为type,而且这种机制是可编程的,称为元类__metaclass__ 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Singleton(type):
  def __init__(self,name,bases,class_dict):
    super(Singleton,self).__init__(name,bases,class_dict)
    self._instance=None
  def __call__(self,*args,**kwargs):
    if self._instance is None:
      self._instance=super(Singleton,self).__call__(*args,**kwargs)
    return self._instance
if __name__=='__main__':
  class A(object):
    __metaclass__=Singleton    
  a=A()
  b=A()
  print id(a),id(b)

结果:

1
43645654 43645654

id是相同的。

例子中我们构造了一个Singleton元类,并使用__call__方法使其能够模拟函数的行为。构造类A时,将其元类设为Singleton,那么创建类对象A时,行为发生如下:

A=Singleton(name,bases,class_dict),A其实为Singleton类的一个实例。

创建A的实例时,A()=Singleton(name,bases,class_dict)()=Singleton(name,bases,class_dict).__call__(),这样就将A的所有实例都指向了A的属性_instance上,这种方法与方法1其实是相同的。

方法4:使用模块

python中的模块module在程序中只被加载一次,本身就是单例的。可以直接写一个模块,将你需要的方法和属性,写在模块中当做函数和模块作用域的全局变量即可,根本不需要写类。

而且还有一些综合模块和类的优点的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
class _singleton(object):
  class ConstError(TypeError):
    pass
  def __setattr__(self,name,value):
    if name in self.__dict__:
      raise self.ConstError
    self.__dict__[name]=value
  def __delattr__(self,name):
    if name in self.__dict__:
      raise self.ConstError
    raise NameError
import sys
sys.modules[__name__]=_singleton()

相关教程