Python基礎之單例模式,內容包括 單例設計模式介紹,__new__方法,Python中的單例。其中,單例設計模式 包括 設計模式,單例模式;__new__方法 包括 __new__作用,重寫__new__方法註意,重寫new方法示例;Python中的單例 包括 單例,單例設計模式思路分析,用ne... ...
單例設計模式
設計模式
- 設計模式是前人工作的總結和提煉,通常,被人們廣為流傳的設計模式都是針對某一特定問題的成熟的解決方案;
- 使用設計模式是為了可重用代碼,讓代碼更容易被他人理解,保證代碼的可靠性;
單例模式
- 目的--讓類創建的對象,在系統中只有唯一一個實例;
- 每一次執行類名()返回的對象,記憶體地址都是相同的;
__new__方法
__new__作用
使用 類名()創建對象時,python解釋器首先會調用__new__方法為對象分配記憶體空間;
__new__是一個由object基類提供的內置的靜態方法;
主要作用有兩個:
- 在記憶體中為對象分配空間;
- 返回對象的引用;
python的解釋器獲得 對象的引用後,將引用作為第一個參數,傳遞給 __init__方法
重寫__new__方法註意
重寫__new__方法的代碼非常固定;
重寫__new__方法一定要 return super().__new__(cls);
否則python的解釋器得不到分配了空間的對象的引用,就不會調用對象的初始化方法;
註意,__new__是一個靜態方法,在調用時需要主動傳遞cls參數;
重寫new方法示例
class MusicPlayer(object):
def __new__(cls, *args, **kwargs):
# 1.創建對象時,new方法會被自動調用
print("__new__方法,創建對象,分配空間")
# 2.為對象分配記憶體空間
instance = super().__new__(cls)
# 3.返回對象的引用
return instance
def __init__(self):
print("__init__, 播放器初始化")
palyer = MusicPlayer()
print(palyer)
# __new__方法,創建對象,分配空間
# __init__, 播放器初始化
# <__main__.MusicPlayer object at 0x00000136237A92E8>
如果new方法不返回super().__new__(cls),就無法執行後續的初始化方法
class MusicPlayer(object):
def __new__(cls, *args, **kwargs):
# 1.創建對象時,new方法會被自動調用
print("__new__方法,創建對象,分配空間")
def __init__(self):
print("__init__, 播放器初始化")
palyer = MusicPlayer()
print(palyer)
# __new__方法,創建對象,分配空間
# None
Python中的單例
單例
單例--讓類創建的對象,在系統中只有唯一一個實例;
1.定義一個類屬性,初始值是None,用於記錄 單例對象的引用;
2.重寫__new__方法
3.如果類屬性 is None,用super()調用父類方法分配空間,併在類屬性中記錄結果;
4.返回類屬性中記錄的對象引用;
單例設計模式思路分析
先設置一個類屬性,初始值為None,
重寫new方法,如果類屬性為None,說明是第一次創建對象,就把創建對象時new方法返回的記憶體地址傳遞給類屬性,
後續再創建對象時,類屬性已經不是None了,在new方法中就直接把類屬性中的值返回,這樣就可以實現 在系統中只有唯一一個實例。
用new方法寫單例模式
用new方法寫單例模式-缺陷版
class MusicPlayer(object):
# 記錄第一個 被創建對象的引用
instance = None
def __new__(cls, *args, **kwargs):
# 判斷類屬性中是否有值,None則說明是第一個被創建的對象
# 如果是第一個對象,就給類屬性賦值對象的引用,返回類屬性記錄的 對象的引用
# 如果不是第一個對象,說明類屬性中已經有了對象的引用,就返回類屬性記錄的 對象的引用
if cls.instance is None:
cls.instance = super().__new__(cls)
return cls.instance
def __init__(self):
print("播放器初始化")
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)
# 播放器初始化
# <__main__.MusicPlayer object at 0x000002C117E892E8>
# 播放器初始化
# <__main__.MusicPlayer object at 0x000002C117E892E8>
用new方法寫單例模式-改進版
存在問題:單例無法只初始化一次
上面存在一個問題,雖然每次返回對象的引用都是一樣的,但是每次創建對象時都需要調用初始化方法,而我們並不需要,因此我們要改造初始化方法,讓它只初始化一次;
在每次使用類名()創建對象時,python的解釋器都會自動調用兩個方法:
__new__分配空間
__init__對象初始化
在上一節中對__new__方法改造之後,每次都會得到第一次被創建獨享的引用
但是:初始化方法還會被再次調用
需求:讓初始化方法只被執行一次
解決方法:
1.定義一個flag標識是否執行過初始化動作,初始值為Flase
2.在init方法中,判斷flag,如果為Flase就執行初始化動作
3.然後將flag設置為True
4.這樣,再次自動調用init方法時,初始化動作就不會被再次執行了。
改進版單例模式示範
class MusicPlayer(object):
# 記錄第一個 被創建對象的引用
instance = None
# 記錄是否執行過初始化動作
flag = False
def __new__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = super().__new__(cls)
return cls.instance
def __init__(self):
# 判斷是否執行過初始化動作
# 執行過,就直接返回,不再執行後續動作
if MusicPlayer.flag:
return
# 沒執行過,說明是第一次初始化,就完成初始化動作,並且修改類屬性標識
print("播放器初始化")
MusicPlayer.flag = True
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)
# 播放器初始化
# <__main__.MusicPlayer object at 0x000001ACFC4F9358>
# <__main__.MusicPlayer object at 0x000001ACFC4F9358>