色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Python實現單例模式的五種寫法

馬哥Linux運維 ? 來源:碼農學習聯盟 ? 2023-05-24 11:27 ? 次閱讀

單例模式(Singleton Pattern)是一種常用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你希望在整個系統中,某個類只能出現一個實例時,單例對象就能派上用場。

比如,某個服務器程序的配置信息存放在一個文件中,客戶端通過一個 AppConfig 的類來讀取配置文件的信息。如果在程序運行期間,有很多地方都需要使用配置文件的內容,也就是說,很多地方都需要創建 AppConfig 對象的實例,這就導致系統中存在多個 AppConfig 的實例對象,而這樣會嚴重浪費內存資源,尤其是在配置文件內容很多的情況下。

事實上,類似 AppConfig 這樣的類,我們希望在程序運行期間只存在一個實例對象。 在 Python 中,我們可以用多種方法來實現單例模式:

使用模塊

使用裝飾器

使用類

基于__new__方法實現

基于 metaclass 方式實現

下面來詳細介紹:

使用模塊 其實,Python 的模塊就是天然的單例模式,因為模塊在第一次導入時,會生成.pyc文件,當第二次導入時,就會直接加載.pyc文件,而不會再次執行模塊代碼。

因此,我們只需把相關的函數和數據定義在一個模塊中,就可以獲得一個單例對象了。

如果我們真的想要一個單例類,可以考慮這樣做:

classSingleton(object):
deffoo(self):
pass
singleton=Singleton()

將上面的代碼保存在文件 mysingleton.py 中,要使用時,直接在其他文件中導入此文件中的對象,這個對象即是單例模式的對象

frommysingletonimportsingleton

使用裝飾器

defSingleton(cls):
_instance={}

def_singleton(*args,**kargs):
ifclsnotin_instance:
_instance[cls]=cls(*args,**kargs)
return_instance[cls]

return_singleton


@Singleton
classA(object):
a=1

def__init__(self,x=0):
self.x=x


a1=A(2)
a2=A(3)

使用類

classSingleton(object):

def__init__(self):
pass

@classmethod
definstance(cls,*args,**kwargs):
ifnothasattr(Singleton,"_instance"):
Singleton._instance=Singleton(*args,**kwargs)
returnSingleton._instance

一般情況,大家以為這樣就完成了單例模式,但是當使用多線程時會存在問題:

classSingleton(object):

def__init__(self):
pass

@classmethod
definstance(cls,*args,**kwargs):
ifnothasattr(Singleton,"_instance"):
Singleton._instance=Singleton(*args,**kwargs)
returnSingleton._instance

importthreading

deftask(arg):
obj=Singleton.instance()
print(obj)

foriinrange(10):
t=threading.Thread(target=task,args=[i,])
t.start()

程序執行后,打印結果如下:

<__main__.Singleton?object?at?0x02C933D0>
<__main__.Singleton?object?at?0x02C933D0>
<__main__.Singleton?object?at?0x02C933D0>
<__main__.Singleton?object?at?0x02C933D0>
<__main__.Singleton?object?at?0x02C933D0>
<__main__.Singleton?object?at?0x02C933D0>
<__main__.Singleton?object?at?0x02C933D0>
<__main__.Singleton?object?at?0x02C933D0>
<__main__.Singleton?object?at?0x02C933D0>
<__main__.Singleton?object?at?0x02C933D0>

看起來也沒有問題,那是因為執行速度過快,如果在__init__方法中有一些 IO 操作,就會發現問題了。

下面我們通過time.sleep模擬,我們在上面__init__方法中加入以下代碼:

def__init__(self):
importtime
time.sleep(1)

重新執行程序后,結果如下:

<__main__.Singleton?object?at?0x034A3410>
<__main__.Singleton?object?at?0x034BB990>
<__main__.Singleton?object?at?0x034BB910>
<__main__.Singleton?object?at?0x034ADED0>
<__main__.Singleton?object?at?0x034E6BD0>
<__main__.Singleton?object?at?0x034E6C10>
<__main__.Singleton?object?at?0x034E6B90>
<__main__.Singleton?object?at?0x034BBA30>
<__main__.Singleton?object?at?0x034F6B90>
<__main__.Singleton?object?at?0x034E6A90>

問題出現了!按照以上方式創建的單例,無法支持多線程。

解決辦法:加鎖!未加鎖部分并發執行,加鎖部分串行執行,速度降低,但是保證了數據安全。

importtime
importthreading


classSingleton(object):
_instance_lock=threading.Lock()

def__init__(self):
time.sleep(1)

@classmethod
definstance(cls,*args,**kwargs):
withSingleton._instance_lock:
ifnothasattr(Singleton,"_instance"):
Singleton._instance=Singleton(*args,**kwargs)
returnSingleton._instance


deftask(arg):
obj=Singleton.instance()
print(obj)


foriinrange(10):
t=threading.Thread(target=task,args=[i,])
t.start()


time.sleep(20)
obj=Singleton.instance()
print(obj)

打印結果如下:

<__main__.Singleton?object?at?0x02D6B110>
<__main__.Singleton?object?at?0x02D6B110>
<__main__.Singleton?object?at?0x02D6B110>
<__main__.Singleton?object?at?0x02D6B110>
<__main__.Singleton?object?at?0x02D6B110>
<__main__.Singleton?object?at?0x02D6B110>
<__main__.Singleton?object?at?0x02D6B110>
<__main__.Singleton?object?at?0x02D6B110>
<__main__.Singleton?object?at?0x02D6B110>
<__main__.Singleton?object?at?0x02D6B110>

這樣就差不多了,但是還是有一點小問題,就是當程序執行時,執行了time.sleep(20)后,下面實例化對象時,此時已經是單例模式了。

但我們還是加了鎖,這樣不太好,再進行一些優化,把intance方法,改成下面這樣就行:

@classmethod
definstance(cls,*args,**kwargs):
ifnothasattr(Singleton,"_instance"):
withSingleton._instance_lock:
ifnothasattr(Singleton,"_instance"):
Singleton._instance=Singleton(*args,**kwargs)
returnSingleton._instance

這樣,一個可以支持多線程的單例模式就完成了。+

importtime
importthreading


classSingleton(object):
_instance_lock=threading.Lock()

def__init__(self):
time.sleep(1)

@classmethod
definstance(cls,*args,**kwargs):
ifnothasattr(Singleton,"_instance"):
withSingleton._instance_lock:
ifnothasattr(Singleton,"_instance"):
Singleton._instance=Singleton(*args,**kwargs)
returnSingleton._instance


deftask(arg):
obj=Singleton.instance()
print(obj)


foriinrange(10):
t=threading.Thread(target=task,args=[i,])
t.start()


time.sleep(20)
obj=Singleton.instance()
print(obj)

這種方式實現的單例模式,使用時會有限制,以后實例化必須通過obj = Singleton.instance()

如果用obj = Singleton(),這種方式得到的不是單例。

基于__new__方法實現

通過上面例子,我們可以知道,當我們實現單例時,為了保證線程安全需要在內部加入鎖。

我們知道,當我們實例化一個對象時,是先執行了類的__new__方法(我們沒寫時,默認調用object.__new__),實例化對象;然后再執行類的__init__方法,對這個對象進行初始化,所有我們可以基于這個,實現單例模式。

importthreading


classSingleton(object):
_instance_lock=threading.Lock()

def__init__(self):
pass


def__new__(cls,*args,**kwargs):
ifnothasattr(Singleton,"_instance"):
withSingleton._instance_lock:
ifnothasattr(Singleton,"_instance"):
Singleton._instance=object.__new__(cls)
returnSingleton._instance

obj1=Singleton()
obj2=Singleton()
print(obj1,obj2)

deftask(arg):
obj=Singleton()
print(obj)

foriinrange(10):
t=threading.Thread(target=task,args=[i,])
t.start()

打印結果如下:

<__main__.Singleton?object?at?0x038B33D0><__main__.Singleton?object?at?0x038B33D0>
<__main__.Singleton?object?at?0x038B33D0>
<__main__.Singleton?object?at?0x038B33D0>
<__main__.Singleton?object?at?0x038B33D0>
<__main__.Singleton?object?at?0x038B33D0>
<__main__.Singleton?object?at?0x038B33D0>
<__main__.Singleton?object?at?0x038B33D0>
<__main__.Singleton?object?at?0x038B33D0>
<__main__.Singleton?object?at?0x038B33D0>
<__main__.Singleton?object?at?0x038B33D0>
<__main__.Singleton?object?at?0x038B33D0>

采用這種方式的單例模式,以后實例化對象時,和平時實例化對象的方法一樣obj = Singleton()。

基于 metaclass 方式實現

相關知識:

類由 type 創建,創建類時,type 的__init__方法自動執行,類() 執行 type 的__call__方法(類的__new__方法,類的__init__方法)

對象由類創建,創建對象時,類的__init__方法自動執行,對象()執行類的__call__方法

例子:

classFoo:
def__init__(self):
pass

def__call__(self,*args,**kwargs):
pass

obj=Foo()
#執行type的__call__方法,調用 Foo類(是type的對象)的__new__方法,用于創建對象,然后調用 Foo類(是type的對象)的__init__方法,用于對對象初始化。

obj()#執行Foo的__call__方法

元類的使用:

classSingletonType(type):
def__init__(self,*args,**kwargs):
super(SingletonType,self).__init__(*args,**kwargs)

def__call__(cls,*args,**kwargs):#這里的cls,即Foo類
print('cls',cls)
obj=cls.__new__(cls,*args,**kwargs)
cls.__init__(obj,*args,**kwargs)#Foo.__init__(obj)
returnobj

classFoo(metaclass=SingletonType):#指定創建Foo的type為SingletonType
def__init__(self,name):
self.name=name
def__new__(cls,*args,**kwargs):
returnobject.__new__(cls)

obj=Foo('xx')

實現單例模式:

importthreading

classSingletonType(type):
_instance_lock=threading.Lock()
def__call__(cls,*args,**kwargs):
ifnothasattr(cls,"_instance"):
withSingletonType._instance_lock:
ifnothasattr(cls,"_instance"):
cls._instance=super(SingletonType,cls).__call__(*args,**kwargs)
returncls._instance

classFoo(metaclass=SingletonType):
def__init__(self,name):
self.name=name


obj1=Foo('name')
obj2=Foo('name')
print(obj1,obj2)

鏈接:https://www.cnblogs.com/huchong/p/8244279.html





審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • python
    +關注

    關注

    56

    文章

    4793

    瀏覽量

    84634

原文標題:Python實現單例模式的五種寫法!

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    談談Python 中的迭代器模式

    中都得到了廣泛的應用。 本文將談談 Python 中的迭代器模式,主要內容:什么是迭代器模式、Python 如何實現迭代器
    發表于 11-23 13:10 ?796次閱讀
    談談<b class='flag-5'>Python</b> 中的迭代器<b class='flag-5'>模式</b>

    verilog語言寫法實現問題!求解答~

    在看verilog代碼時,看到這樣兩表示方法:一是:“ wirea;assigna=b;”一是:“wirea=b;”請教各位大神這兩寫法
    發表于 01-29 14:33

    Python常用自增運算寫法

    在學習任何一編程語言,運算方法的學習是不可避免的,其中自增運算符++的使用也是其中的重點,很多人容易弄不明白其用法,尤其是在Python中,其用法更加的不同!我們可以寫個實例來說明一下++運算符在
    發表于 04-09 17:45

    怎么通過運動檢測模式實現應用產品的變革?

    通過審視運動檢測模式——加速度(包括平移運動,如位置和方向)、振動、沖擊、傾斜和旋轉,各自的可能性,可以超越當今大量MEMS應用的范圍,極大地擴大應用選項。MEMS加速度計和陀螺儀如何通過
    發表于 07-30 07:47

    Python驅動程序實現輪電機的速度控制

    在有了別人的代碼后,我就很容易的參考他的方法來實現電機的這個功能,因此我簡單的寫了一個Python程序,通過調用之前寫的Python驅動程序,實現了對
    發表于 09-07 06:18

    PWM反饋控制模式研究

    PWM反饋控制模式研究
    發表于 08-08 10:46 ?20次下載
    <b class='flag-5'>五</b><b class='flag-5'>種</b>PWM反饋控制<b class='flag-5'>模式</b>研究

    模式詳解

    是private的話,會不更好的封裝該內呢?我主要是應用在使用普通類模擬枚舉類型里,后來發現這就是傳說中的模式。構造函數弄成private 就是
    發表于 09-27 15:10 ?0次下載

    模式分成餓漢模式和懶漢模式解析

    定義:作為對象的創建模式,模式確保某一個類只有一個實例,而且自行實例化并向整個系統提供這個實例。這個類稱為
    發表于 12-11 09:49 ?1649次閱讀

    Python下劃線的模式和命名約定

    本文介紹了Python下劃線和雙下劃線("dunder")的各種含義和命名約定,名稱修飾(name mangling)的工作原理,以及它如何影響你自己的Python類。
    的頭像 發表于 12-30 16:40 ?2012次閱讀
    <b class='flag-5'>Python</b><b class='flag-5'>五</b><b class='flag-5'>種</b>下劃線的<b class='flag-5'>模式</b>和命名約定

    Python略高級特征的使用方法

    Python 多好用不用多說,大家看看自己用的語言就知道了。但是 Python 隱藏的高級功能你都 get 了嗎?本文中,作者列舉了 Python
    的頭像 發表于 04-24 10:12 ?3212次閱讀

    開關電源PWM 反饋控制模式

    開關電源PWM 反饋控制模式(新型電源技術作業答案)-開關電源PWM 反饋控制模式
    發表于 09-27 10:01 ?76次下載
    開關電源PWM <b class='flag-5'>五</b><b class='flag-5'>種</b>反饋控制<b class='flag-5'>模式</b>

    詳解golang事務的三寫法

    本文中作者展示了 golang 事務的三寫法。
    的頭像 發表于 03-16 08:52 ?5293次閱讀

    60個python日常高頻寫法

    今天給大家準備了60個python日常高頻寫法,如果覺得有用,那就點贊收藏起來吧~
    的頭像 發表于 04-16 09:49 ?1030次閱讀

    模式(Singleton Pattern)實現的方法

    模式是指某個類只允許存在一個實例對象,例如在打印機打印文件時,一次只允許打印一個文件
    的頭像 發表于 06-01 11:44 ?634次閱讀
    <b class='flag-5'>單</b><b class='flag-5'>例</b><b class='flag-5'>模式</b>(Singleton Pattern)<b class='flag-5'>實現</b>的方法

    insert into 語句的三寫法

    INSERT INTO是MySQL中常用的一SQL語句,用于將數據插入到表中。此文將詳細介紹INSERT INTO語句的三不同寫法及其用途,并提供代碼示例和相關解釋。 正文: 一、基本插入
    的頭像 發表于 11-21 14:18 ?1.3w次閱讀
    主站蜘蛛池模板: 古代荡女丫鬟高H辣文纯肉| 亚洲黄视频在线观看| 一个人的免费高清影院| 久热久热精品在线观看| 啊灬啊灬啊灬快高潮视频| 748亚洲大胆国模人体| 日韩一区二区天海翼| 九九热视频在线观看| 狠狠色丁香婷婷久久综合| 国产女人毛片| 99er4久久视频精品首页| 视频一区在线免费观看| 麻豆官网md.pub| 毛茸茸womansex| 内地同志男16china16| 国自精品三七区| 护士们的母狗| 久草色在线| 久久一er精这里有精品| 岛国片在线免费观看| 东北疯狂xxxxbbbb中国| 国产AV国产精品国产三级在线L| 俄罗斯女人Z0Z0极品| 国产麻豆剧看黄在线观看| av天堂网2017avtt| 在线 无码 中文 强 乱| 中文无码不卡的岛国片国产片| 鸭子玩富婆流白浆视频| 亚洲高清毛片一区二区| 一本之道高清在线观看一区| 中文在线日韩亚洲制服| av先锋影音资源男人站| 高清欧美性猛交xxxx黑人猛交| 国产99久久亚洲综合精品西瓜tv| 国产免国产免费| 久久国产36精品色熟妇| 国产亚洲精品久久久999无毒| 大乳牛奶女magnet| 国产精品久久人妻无码网站一区无 | 嗯啊不要老师| 三叶草成人|