在 Python 中實現單例模式

2021-08-10 11:55:20 字數 3150 閱讀 2621

cyrusin.github.io/2015/09/15/python-singleton-20150915/

有些時候你的專案中難免需要一些全域性唯一的物件,這些物件大多是一些工具性的東西,在python中實現單例模式並不是什麼難事。以下總結幾種方法:

使用類裝飾器

使用裝飾器實現單例類的時候,類本身並不知道自己是單例的,所以寫**的人可以不care這個,只要正常寫自己的類的實現就可以,類的單例有裝飾器保證。

def singleton

(cls):

instances

= {}(*

args,**

kwargs):

ifcls

notin

instances

:instances

[cls]=

cls(

*args,**

kwargs

)return

instances

[cls

]return

你會發現singleton裝飾器內部使用了乙個dict。當然你也可以用其他的方式,不過以下的實現是錯誤的:

def singleton

(cls):

_instance

= none

#外部作用域的引用對於巢狀的內部作用域是唯讀的(*

args,**

kwargs):

if_instance

isnone

: #直譯器會丟擲"unboundlocalerror: ...referenced before assignment"

_instance

= cls(*

args,**

kwargs

)#賦值行為使直譯器將"_instance"看作區域性變數

return

_instance

return

使用元類(__metaclass__)和可呼叫物件(__call__)

python的物件系統中一些皆物件,類也不例外,可以稱之為」型別物件」,比較繞,但仔細思考也不難:類本身也是一種物件,只不過這種物件很特殊,它表示某一種型別。是物件,那必然是例項化來的,那麼誰例項化後是這種型別物件呢?也就是元類。

python中,class關鍵字表示定義乙個類物件,此時直譯器會按一定規則尋找__metaclass__,如果找到了,就呼叫對應的元類實現來例項化該類物件;沒找到,就會呼叫type元類來例項化該類物件。

__call__是python的魔術方法,python的物件導向是」duck type」的,意味著物件的行為可以通過實現協議來實現,可以看作是一種特殊的介面形式。某個類實現了__call__方法意味著該類的物件是可呼叫的,可以想像函式呼叫的樣子。再考慮一下foo=foo()這種例項化的形式,是不是很像啊。結合元類的概念,可以看出,foo類是單例的,則在呼叫foo()的時候每次都返回了同樣的物件。而foo作為乙個類物件是單例的,意味著它的類(即生成它的元類)是實現了__call__方法的。所以可以如下實現:

class

singleton

(type):

def __init__

(cls

,name

,bases

,attrs):

super

(singleton

,cls

).__init__

(name

,bases

,attrs

)cls

._instance

= none

def __call__

(cls,*

args,**

kwargs):

ifcls

._instance

isnone

# 以下不要使用'cls._instance = cls(*args, **kwargs)', 防止死迴圈,

# cls的呼叫行為已經被當前'__call__'協議攔截了

# 使用super(singleton, cls).__call__來生成cls的例項

cls.

_instance

= super

(singleton

,cls

).__call__(*

args,**

kwargs

)return

cls.

_instance

class

foo(

object):

#單例類

__metaclass__

= singleton

>>>a=

foo()

>>>b=

foo()

>>>ais

b>>>

true

>>>a.

x= 1>>>b.

x>>>

1

使用__new__

__init__不是python物件的構造方法,__init__只負責初始化例項物件,在呼叫__init__方法之前,會首先呼叫__new__方法生成物件,可以認為__new__方法充當了構造方法的角色。所以可以在__new__中加以控制,使得某個類只生成唯一物件。具體實現時可以實現乙個父類,過載__new__方法,單例類只需要繼承這個父類就好。

class

singleton

(object):

def __new__

(cls,*

args,**

kwargs):

ifnot

hasattr

(cls

,'_instance'):

cls.

_instance

= super

(singleton

,cls

).__new__

(cls,*

args,**

kwargs

)return

cls.

_instance

class

foo(

singleton):

#單例類a=

1

python中單例模式的實現

單例模式 保證系統中乙個類只有乙個例項而且該例項利於外界訪問。下面是python實現單例模式的一種方式。這裡用了重寫new方法來實現單例模式。在python中 new 方法是乙個靜態方法 它在物件被建立時呼叫,為物件分配空間,並且返回乙個位址傳給 init 方法 new 方法的第乙個引數是表示當前類...

python實現單例模式

最近在寫乙個連線池,而連線池管理類不可避免的需要使用單例來保證所有使用者在取得連線時取到的一定是同乙個管理物件。故將此模式取來研究一番。保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點 設計模式 單例模式是全域性只有乙個訪問點,故對於乙個類來說,任何例項化後訪問到的都應該是同樣的物件。而也有另...

Python 實現單例模式

encoding utf 8 print 方法1 方法1,實現 new 方法 並在將乙個類的例項繫結到類變數 instance上,如果cls.instance為none說明該類還沒有例項化過,例項化該類,並返回 如果cls.instance不為none,直接返回cls.instance class ...