單例模式是一個常用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。比如說:利用加標簽的白名單防止跨站腳本攻擊XXS創建一個XxsFile類,不同的人訪問都要創建XxsFile對象的實例,這就導致系統中存在多個XxsFile的實例對象,而這樣會嚴重浪費內存資源。事實上類似於XxsFile這樣的類,我們希望在程序運行期間只存在一個實例對象,在python中,我們可以使用單例。如下列幾種方法:
在Python中new方法和init方法類似,但是如果兩個都存在那么new先執行
__new__(cls, *args, **kwargs)
__new__()中的需要傳遞一個參數cls,cls表示需要實例化的類,此參數在實例化時由Python解析器自動提供1、類方法classmethod
# -*-coding:utf-8 -*-
class Foo(object):
__instance = None
@classmethod
def instance(self):
if self.__instance:
return self.__instance
else:
obj = self()
self.__instance = obj
return self.__instance
obj1=Foo.instance()
obj2=Foo.instance()
print(obj1,obj2)
2、基於__new__方法實現(推薦使用、方便)
當我們實例化一個對象時,是先執行了類的__new__方法(當我們沒寫時,默認調用object.__new__),實例化對象;然后再執行類的__init__方法,對這個對象進行初始化,所以我們可以基於這個,實現單例模式:
# -*-coding:utf-8 -*-
class Foo(object):
__instance=None
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if cls.__instance:
return cls.__instance
else:
obj = object.__new__(cls,*args,**kwargs)
cls.__instance = obj
return cls.__instance
obj1=Foo()
obj2=Foo()
print(obj1,obj2)
Python new()方法,為對象分配內存,返回對象的引用
# -*-coding:utf-8 -*-
class MusicPlayer(object):
#為對象分配內存空間
def __new__(cls, *args, **kwargs):
#1、創建對象時,new方法會被自動調用
print("創建對象,分配內存空間")
#2、為對象分配空間
instance = super().__new__(cls)
#3、返回對象引用
return instance
#對象初始化,定義實例屬性
def __init__(self):
print("播放器初始化")
#創建播放器對象
player = MusicPlayer()
print(player)
__new__方法:
使用MusicPlayer()創建對象時,python的解釋器首先會調用__new__方法為對象分配空間,如果不分配空間那么就不會調用初始化__init__,__new__是一個由object基類提供的內置的靜態方法,主要作用有兩個:
1、在內存空間中為對象分配空間
2、返回對象的引用
Python的解釋器獲取得到對象的引用后,將引用作為第一個參數,傳遞給__init__,
1、重寫__new__方法python用return super().__new__(cls),否則Python的解釋器得不到分配了空間的對象引用,就不會調用對象的初始化方法,注意:__new__是一個靜態方法,在調用時需要主動傳遞cls參數
如果分配了內存空間,就會調用初始化__init__的結果:
# -*-coding:utf-8 -*-
class MusicPlayer(object):
#為對象分配內存空間
def __new__(cls, *args, **kwargs):
#1、創建對象時,new方法會被自動調用
print("創建對象,分配內存空間")
#2、為對象分配空間
instance = super().__new__(cls)
#3、返回對象引用
return instance
#對象初始化,定義實例屬性
def __init__(self):
print("播放器初始化")
#創建播放器對象
player = MusicPlayer()
print(player)
#輸出:
# 創建對象,分配內存空間
# 播放器初始化
# <__main__.MusicPlayer object at 0x033D09B0>
如果__new__不分配內存空間,創建對象的時候就不會去的調用__init__,結果如下:
# -*-coding:utf-8 -*-
class MusicPlayer(object):
#為對象分配內存空間
def __new__(cls, *args, **kwargs):
#1、創建對象時,new方法會被自動調用
print("創建對象,分配內存空間")
#對象初始化,定義實例屬性
def __init__(self):
print("播放器初始化")
#創建播放器對象
player = MusicPlayer()
print(player)
#輸出:
#創建對象,分配內存空間
#None
