python

超轻量级php框架startmvc

单利模式及python实现方式详解

更新时间:2020-05-25 04:00:02 作者:startmvc
单例模式单例模式(SingletonPattern)是一种常用的软件设计模式,该模式的主要目的是确保

单例模式

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保 某一个类只有一个实例存在 。当希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象

python实现单例模式

使用模块实现

Python 的模块就是天然的单例模式 ,因为模块在第一次导入时,会生成  .pyc 文件,当第二次导入时,就会直接加载  .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。

mysingleton.py


class Singleton:
 def foo(self):
 print('foo')
singleton=Singleton()

其他文件


from mysingleton import singleton
singleton.foo()

装饰器实现


def singleton(cls):
 _instance = {}
 def wraper(*args, **kargs):
 if cls not in _instance:
 _instance[cls] = cls(*args, **kargs)
 return _instance[cls]
 return wraper
@singleton
class A(object):
 def __init__(self, x=0):
 self.x = x
a1 = A(2)
a2 = A(3)

最终实例化出一个对象并且保存在_instance中,_instance的值也一定是

基于__new__方法实现

当我们实例化一个对象时,是 先执行了类的__new__方法 (我们没写时,默认调用object.__new__), 实例化对象 ;然后 再执行类的__init__方法 ,对这个对象进行初始化,所有我们可以基于这个,实现单例模式


class Singleton():
 def __new__(cls, *args, **kwargs):
 if not hasattr(cls,'_instance'):
 cls._instance=object.__new__(cls)
 return cls._instance

class A(Singleton):
 def __init__(self,x):
 self.x=x

a=A('han')
b=A('tao')
print(a.x)
print(b.x)

为了保证线程安全需要在内部加入锁


import threading

class Singleton():
 lock=threading.Lock
 def __new__(cls, *args, **kwargs):
 if not hasattr(cls,'_instance'):
 with cls.lock:
 if not hasattr(cls, '_instance'):
 cls._instance=object.__new__(cls)
 return cls._instance
class A(Singleton):
 def __init__(self,x):
 self.x=x
a=A('han')
b=A('tao')
print(a.x)
print(b.x)

两大注意:

1. 除了模块单例外,其他几种模式的本质都是通过设置中间变量,来判断类是否已经被实例。中间变量的访问和更改存在线程安全的问题:在开启多线程模式的时候需要加锁处理。

2.  __new__方法无法避免触发__init__(),初始的成员变量会进行覆盖。 其他方法不会。

PS:下面看下Python单例模式的4种实现方法


#-*- encoding=utf-8 -*- 
print '----------------------方法1--------------------------' 
#方法1,实现__new__方法 
#并在将一个类的实例绑定到类变量_instance上, 
#如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回 
#如果cls._instance不为None,直接返回cls._instance 
class Singleton(object): 
 def __new__(cls, *args, **kw): 
 if not hasattr(cls, '_instance'): 
 orig = super(Singleton, cls) 
 cls._instance = orig.__new__(cls, *args, **kw) 
 return cls._instance 
class MyClass(Singleton): 
 a = 1 
one = MyClass() 
two = MyClass() 
two.a = 3 
print one.a 
#3 
#one和two完全相同,可以用id(), ==, is检测 
print id(one) 
#29097904 
print id(two) 
#29097904 
print one == two 
#True 
print one is two 
#True 
print '----------------------方法2--------------------------' 
#方法2,共享属性;所谓单例就是所有引用(实例、对象)拥有相同的状态(属性)和行为(方法) 
#同一个类的所有实例天然拥有相同的行为(方法), 
#只需要保证同一个类的所有实例具有相同的状态(属性)即可 
#所有实例共享属性的最简单最直接的方法就是__dict__属性指向(引用)同一个字典(dict) 
#可参看:http://code.activestate.com/recipes/66531/ 
class Borg(object): 
 _state = {} 
 def __new__(cls, *args, **kw): 
 ob = super(Borg, cls).__new__(cls, *args, **kw) 
 ob.__dict__ = cls._state 
 return ob 
class MyClass2(Borg): 
 a = 1 
one = MyClass2() 
two = MyClass2() 
#one和two是两个不同的对象,id, ==, is对比结果可看出 
two.a = 3 
print one.a 
#3 
print id(one) 
#28873680 
print id(two) 
#28873712 
print one == two 
#False 
print one is two 
#False 
#但是one和two具有相同的(同一个__dict__属性),见: 
print id(one.__dict__) 
#30104000 
print id(two.__dict__) 
#30104000 
print '----------------------方法3--------------------------' 
#方法3:本质上是方法1的升级(或者说高级)版 
#使用__metaclass__(元类)的高级python用法 
class Singleton2(type): 
 def __init__(cls, name, bases, dict): 
 super(Singleton2, cls).__init__(name, bases, dict) 
 cls._instance = None 
 def __call__(cls, *args, **kw): 
 if cls._instance is None: 
 cls._instance = super(Singleton2, cls).__call__(*args, **kw) 
 return cls._instance 
class MyClass3(object): 
 __metaclass__ = Singleton2 
one = MyClass3() 
two = MyClass3() 
two.a = 3 
print one.a 
#3 
print id(one) 
#31495472 
print id(two) 
#31495472 
print one == two 
#True 
print one is two 
#True 
print '----------------------方法4--------------------------' 
#方法4:也是方法1的升级(高级)版本, 
#使用装饰器(decorator), 
#这是一种更pythonic,更elegant的方法, 
#单例类本身根本不知道自己是单例的,因为他本身(自己的代码)并不是单例的 
def singleton(cls, *args, **kw): 
 instances = {} 
 def _singleton(): 
 if cls not in instances: 
 instances[cls] = cls(*args, **kw) 
 return instances[cls] 
 return _singleton 
@singleton 
class MyClass4(object): 
 a = 1 
 def __init__(self, x=0): 
 self.x = x 
one = MyClass4() 
two = MyClass4() 
two.a = 3 
print one.a 
#3 
print id(one) 
#29660784 
print id(two) 
#29660784 
print one == two 
#True 
print one is two 
#True 
one.x = 1 
print one.x 
#1 
print two.x 
#1 

总结

以上所述是小编给大家介绍的python实现单利模式方式方式详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

python 单利模式 python的实现方式