博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2.1.4 Python单例模式
阅读量:6290 次
发布时间:2019-06-22

本文共 6289 字,大约阅读时间需要 20 分钟。

本节目录


保证一个类只有一个实例,并提供一个访问它的全局访问点

单例,即只有一个类的实例

当类只有一个实例而且客户可以从一个众所周知的访问点访问它时 比如:数据库链接、Socket创建链接

  • 对唯一实例的受控访问
  • 对唯一实例的受控访问

单利相当于全局变量,但防止了命名空间被污染 与单利模式功能相似的概念:全局变量、静态变量(方法)

试问?为什么用单例模式,不用全局变量呢?

  答、全局变量可能会有名称空间的干扰,如果有重名的可能会被覆盖

1、文件导入的形式(常用)

s1.pyclass Foo(object):    def test(self):        print("123")v = Foo()#v是Foo的实例s2.pyfrom s1 import v as v1print(v1,id(v1))  #
35788560from s1 import v as v2print(v1,id(v2)) #
35788560## 两个的内存地址是一样的## 文件加载的时候,第一次导入后,再次导入时不会再重新加载。复制代码

2、基于类实现的单例模式

## **********************单例模式:无法支持多线程情况**************=class Singleton(object):    def __init__(self):        import time        time.sleep(1)    @classmethod    def instance(cls, *args, **kwargs):        if not hasattr(Singleton, "_instance"):            Singleton._instance = Singleton(*args, **kwargs)        return Singleton._instanceimport threadingdef task(arg):    obj = Singleton.instance()    print(obj)for i in range(10):    t = threading.Thread(target=task,args=[i,])    t.start()## ********************单例模式:支持多线程情况****************、import timeimport threadingclass Singleton(object):    _instance_lock = threading.Lock()    def __init__(self):        time.sleep(1)    @classmethod    def instance(cls, *args, **kwargs):        if not hasattr(Singleton, "_instance"):            with Singleton._instance_lock:   #为了保证线程安全在内部加锁                if not hasattr(Singleton, "_instance"):                    Singleton._instance = Singleton(*args, **kwargs)        return Singleton._instancedef task(arg):    obj = Singleton.instance()    print(obj)for i in range(10):    t = threading.Thread(target=task,args=[i,])    t.start()time.sleep(20)obj = Singleton.instance()print(obj)## 使用先说明,以后用单例模式,obj = Singleton.instance()## 示例:## obj1 = Singleton.instance()## obj2 = Singleton.instance()## print(obj1,obj2)## 错误示例## obj1 = Singleton()## obj2 = Singleton()## print(obj1,obj2)复制代码

3、基于__new__实现的单例模式(最常用)

class Singleton:    def __new__(cls, *args, **kw):        if not hasattr(cls, '_instance'):            cls._instance = object.__new__(cls, *args, **kw)        return cls._instanceone = Singleton()two = Singleton()two.a = 3print(one.a)## 3## one和two完全相同,可以用id(), **, is检测print(id(one))## 29097904print(id(two))## 29097904print(one ** two)## Trueprint(one is two)复制代码

4、基于metaclass(元类)实现的单例模式

"""1.对象是类创建,创建对象时候类的__init__方法自动执行,对象()执行类的 __call__ 方法2.类是type创建,创建类时候type的__init__方法自动执行,类() 执行type的 __call__方法(类的__new__方法,类的__init__方法)## 第0步: 执行type的 __init__ 方法【类是type的对象】class Foo:    def __init__(self):        pass    def __call__(self, *args, **kwargs):        pass## 第1步: 执行type的 __call__ 方法##        1.1  调用 Foo类(是type的对象)的 __new__方法,用于创建对象。##        1.2  调用 Foo类(是type的对象)的 __init__方法,用于对对象初始化。obj = Foo()## 第2步:执行Foo的 __call__ 方法obj()"""## **********=类的执行流程****************class SingletonType(type):    def __init__(self,*args,**kwargs):        print(self)  #会不会打印?  #
super(SingletonType,self).__init__(*args,**kwargs) def __call__(cls, *args, **kwargs): #cls = Foo obj = cls.__new__(cls, *args, **kwargs) obj.__init__(*args, **kwargs) return objclass Foo(metaclass=SingletonType): def __init__(self,name): self.name = name def __new__(cls, *args, **kwargs): return object.__new__(cls, *args, **kwargs)''' 1、对象是类创建的,创建对象时类的__init__方法会自动执行,对象()执行类的__call__方法 2、类是type创建的,创建类时候type类的__init__方法会自动执行,类()会先执行type的__call__方法(调用类的__new__,__init__方法) Foo 这个类是由SingletonType这个类创建的'''obj = Foo("hiayan")## ************第三种方式实现单例模式****************=import threadingclass SingletonType(type): _instance_lock = threading.Lock() def __call__(cls, *args, **kwargs): if not hasattr(cls, "_instance"): with SingletonType._instance_lock: if not hasattr(cls, "_instance"): cls._instance = super(SingletonType,cls).__call__(*args, **kwargs) return cls._instanceclass Foo(metaclass=SingletonType): def __init__(self,name): self.name = nameobj1 = Foo('name')obj2 = Foo('name')print(obj1,obj2)复制代码

import pymysqlimport threadingfrom DBUtils.PooledDB import PooledDBclass SingletonDBPool(object):    _instance_lock = threading.Lock()    def __init__(self):        self.pool = PooledDB(            creator=pymysql,  ## 使用链接数据库的模块            maxconnections=6,  ## 连接池允许的最大连接数,0和None表示不限制连接数            mincached=2,  ## 初始化时,链接池中至少创建的空闲的链接,0表示不创建            maxcached=5,  ## 链接池中最多闲置的链接,0和None不限制            maxshared=3,            ## 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。            blocking=True,  ## 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错            maxusage=None,  ## 一个链接最多被重复使用的次数,None表示无限制            setsession=[],  ## 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]            ping=0,            ## ping MySQL服务端,检查是否服务可用。## 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always            host='127.0.0.1',            port=3306,            user='root',            password='123',            database='pooldb',            charset='utf8'        )    def __new__(cls, *args, **kwargs):        if not hasattr(SingletonDBPool, "_instance"):            with SingletonDBPool._instance_lock:                if not hasattr(SingletonDBPool, "_instance"):                    SingletonDBPool._instance = object.__new__(cls, *args, **kwargs)        return SingletonDBPool._instance    def connect(self):        return self.pool.connection()复制代码

from pool import SingletonDBPooldef run():    pool = SingletonDBPool()    conn = pool.connect()    ## xxxxxx    cursor = conn.cursor()    cursor.execute("select * from td where id=%s", [5, ])    result = cursor.fetchall()  ## 获取数据    cursor.close()    conn.close()if __name__ ** '__main__':    run()复制代码

#def wrapper(cls):    instance = {}    def inner(*args,**kwargs):        if cls not in  instance:            instance[cls] = cls(*args,**kwargs)        return instance[cls]    return inner@wrapperclass Singleton(object):    def __init__(self,name,age):        self.name = name        self.age = ageobj1 = Singleton('haiyan',22)obj2 = Singleton('xx',22)print(obj1)print(obj2)复制代码

转载于:https://juejin.im/post/5c45897ae51d4552475ff1de

你可能感兴趣的文章
我的友情链接
查看>>
使用windows 7 系统安装盘 DOS普通用户提权为管理员
查看>>
老男孩教育每日一题第115天:如何在centos 6下面实现命令补全?效果如下
查看>>
国内可用的yum源
查看>>
linux df -h 命令卡住 解决方法
查看>>
spring是什么,Spring能帮我们做什么
查看>>
Codeforces 861D - Polycarp's phone book
查看>>
FreePortScanner.java
查看>>
HttpURLConnection 文件上传限制
查看>>
javascript类式继承新的尝试
查看>>
真正掌握vuex的使用方法(四)
查看>>
MySql的Communications link failure解决办法
查看>>
GB2312编码
查看>>
架构探险笔记2
查看>>
sparse bayesian model
查看>>
jQuery 无刷新评论
查看>>
Oracle临时表
查看>>
Linux下配置一个VNC服务器
查看>>
jquery-form 中文API
查看>>
谈谈NITE 2的第一个程序UserViewer
查看>>