單例模式是什么,2.1.4 Python單例模式

 2023-10-05 阅读 30 评论 0

摘要:點擊跳轉Python筆記總目錄 本節目錄 一、內容 二、角色 三、使用場景 四、優點 五、單例模式的四種實現方式 1、文件導入的形式(常用)2、基于類實現的單例模式3、基于__new__實現的單例模式(最常用4、基于metaclass(元類)實現的單例模式六、單例模式的應用(會在

點擊跳轉Python筆記總目錄

本節目錄

一、內容

二、角色

三、使用場景

四、優點

五、單例模式的四種實現方式

  • 1、文件導入的形式(常用)
  • 2、基于類實現的單例模式
  • 3、基于__new__實現的單例模式(最常用
  • 4、基于metaclass(元類)實現的單例模式

六、單例模式的應用(會在數據庫連接池中用到單例模式)

七、額外補充的一種用裝飾器實現的單利模式


一、內容

保證一個類只有一個實例,并提供一個訪問它的全局訪問點

二、角色

單例,即只有一個類的實例

三、使用場景

單例模式是什么?當類只有一個實例而且客戶可以從一個眾所周知的訪問點訪問它時 比如:數據庫鏈接、Socket創建鏈接

四、優點

  • 對唯一實例的受控訪問
  • 對唯一實例的受控訪問

單利相當于全局變量,但防止了命名空間被污染 與單利模式功能相似的概念:全局變量、靜態變量(方法)

試問?為什么用單例模式,不用全局變量呢?

??答、全局變量可能會有名稱空間的干擾,如果有重名的可能會被覆蓋

五、單例模式的四種實現方式

python元類,1、文件導入的形式(常用)

s1.pyclass Foo(object):def test(self):print("123")v = Foo()
#v是Foo的實例s2.py
from s1 import v as v1
print(v1,id(v1))  #<s1.Foo object at 0x0000000002221710> 35788560from s1 import v as v2
print(v1,id(v2))   #<s1.Foo object at 0x0000000002221710> 35788560## 兩個的內存地址是一樣的
## 文件加載的時候,第一次導入后,再次導入時不會再重新加載。
復制代碼

2、基于類實現的單例模式

## **********************單例模式:無法支持多線程情況**************=class Singleton(object):def __init__(self):import timetime.sleep(1)@classmethoddef 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 time
import threading
class Singleton(object):_instance_lock = threading.Lock()def __init__(self):time.sleep(1)@classmethoddef 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 = 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)復制代碼

4、基于metaclass(元類)實現的單例模式

"""
1.對象是類創建,創建對象時候類的__init__方法自動執行,對象()執行類的 __call__ 方法
2.類是type創建,創建類時候type的__init__方法自動執行,類() 執行type的 __call__方法(類的__new__方法,類的__init__方法)## 第0步: 執行type的 __init__ 方法【類是type的對象】
class Foo:def __init__(self):passdef __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)  #會不會打印?  #<class '__main__.Foo'>super(SingletonType,self).__init__(*args,**kwargs)def __call__(cls, *args, **kwargs):  #cls = Fooobj = cls.__new__(cls, *args, **kwargs)obj.__init__(*args, **kwargs)return objclass Foo(metaclass=SingletonType):def __init__(self,name):self.name = namedef __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)
復制代碼

六、單例模式的應用(會在數據庫連接池中用到單例模式)

mysql 優化,pool.py

import pymysql
import threading
from 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 = alwayshost='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._instancedef connect(self):return self.pool.connection()
復制代碼

app.py

from pool import SingletonDBPooldef run():pool = SingletonDBPool()conn = pool.connect()## xxxxxxcursor = 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@wrapper
class Singleton(object):def __init__(self,name,age):self.name = nameself.age = ageobj1 = Singleton('haiyan',22)
obj2 = Singleton('xx',22)
print(obj1)
print(obj2)
復制代碼

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/117719.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息