16 - 單例模式&魔法方法📄目錄1 單例模式1.1 實現單例模式的方式1.1.1 通過@classmethod1.1.2 通過裝飾器實現1.1.3 通過重寫__new__()實現(常用、重點)1.1.4 通過導入模塊實現1.2 應用場景2 魔法方法2.1 類的描述信息 __doc__()2.2 __module__()和__class__()2.3 __str__():對象的描述信息2.4 __call__():使一個實例對象成為一個「可調用對象」,像函數那樣可以調用導航連結:
可以理解成一個特殊的類,這個類只存在一個對象
單例模式:每一次實例化所創建的對象都是同一個,內存地址都一樣
優點:可以節省內存空間,減少非必要的資源浪費
缺點:多線程訪問的時候容易引發線程安全的問題
__new__()實現(常用、重點)
❗ 當實例化不同對象的時候,內存地址會發生變化
xxxxxxxxxxclass A(object): passa1 = A()print(a1)a2 = A()print(a2)輸出結果:
xxxxxxxxxx<__main__.A object at 0x102467e50><__main__.A object at 0x102467ed0>👉🏻 內存地址發生變化,說明是不同的對象
💡 實現單例模式,對象的內存地址都會是一樣的,只有一個對象
💡 設計流程:
定義一個類屬性,初始值為None,用來記錄單例對象的引用
重寫__new__()方法
進行判斷,如果類屬性是None,把__new__()返回的對象引用保存進去
返回類屬性中記錄的對象引用

xxxxxxxxxxclass Singleton(object): # 記錄第一個被創建的對象的引用 obj = None # 類屬性 def __new__(cls, *args, **kwargs): print("This is __new__") # 要判斷類屬性是否為空 if cls.obj is None: cls.obj = super().__new__(cls) return cls.obj def __init__(self): print("This is __init__")s = Singleton()print(f's:{s}')s2 = Singleton()print(f's2:{s2}')# 單例模式:每一次實例化所創建的對象都是同一個,內存地址都一樣輸出結果:
xxxxxxxxxxThis is __new__This is __init__s:<__main__.Singleton object at 0x1043f9550>This is __new__This is __init__s2:<__main__.Singleton object at 0x1043f9550>
模塊就是天然的單例模式,但是比較雞肋

在當前文件夾建立pytest3.py,並輸入:
xxxxxxxxxxclass Test(object): def test(self): print('test')te =Test()然後在本文件運行以下代碼:
xxxxxxxxxxfrom pytest3 import te as te01from pytest3 import te as te02print(te01, id(te01))print(te02, id(te02))輸出結果:
xxxxxxxxxx<pytest3.Test object at 0x1011c8150> 4313612624<pytest3.Test object at 0x1011c8150> 4313612624回收站對象
音樂播放器,一個音樂播放軟件負責音樂播放的對象只有一個
開發遊戲軟件——場景管理器
數據庫配置、數據庫連接池的設計(節省打開或者關閉的效率消耗)
含義:在Python中,__xx__()的函數被稱為魔法方法,指具有特殊功能的函數
__new__():在內存中為對象分配空間並返回對象的引用
__init__():初始化對象或給屬性賦值
__doc__:類的描述信息
__module__:表示當前操作對象所在模塊
__class__:表示當前操作對象所在的類
__str__():對象的描述信息
__del__():刪除對象(析構函數)
__call__():使一個實例對象成為一個可調用對象
__dict__():返回對象具有的屬性和方法
__doc__()
xxxxxxxxxxclass Person(object): """Person類的描述信息""" passprint(Person.__doc__)輸出結果:
xxxxxxxxxxPerson類的描述信息__module__()和__class__()
在當前文件夾建立pytest3.py,並輸入:
xxxxxxxxxxclass B: def func1(self): print('laugh')然後在本文件運行以下代碼:
xxxxxxxxxximport pytest3b = pytest3.B()print(b.__module__)print(b.__class__)輸出結果:
xxxxxxxxxxpytest3<class 'pytest3.B'>__str__():對象的描述信息💡 如果類中定義了此方法,那麼在打印對象時,默認輸出該方法的返回值,即打印方法中return的數據
❗ 注意:__str__()必須返回一個字符串

xxxxxxxxxxclass C: def __str__(self): return '這裡是str的返回值' # 必須要有返回值,並且必須為字符串類型c = C()print(c)輸出結果:
xxxxxxxxxx這裡是str的返回值__call__():使一個實例對象成為一個「可調用對象」,像函數那樣可以調用可調用對象:凡是可以把一對()應用到某個對象上,都可以被稱為可調用對象
例子:函數、內置函數、類

callable():判斷一個對象是否可調用對象
xxxxxxxxxxdef func(): print('laugh')print(callable(func)) # 返回True,是可調用對象name = 'Amy'print(callable(name)) # 返回False,不是可調用對象輸出結果:
xxxxxxxxxxTrueFalse
xxxxxxxxxxclass A: passa = A()print(callable(a))class B: def __call__(self): print('This is __call__()')b = B() # 調用一個可調用的實例對象,其實就是在調用它的__call__()方法print(callable(b))輸出結果:
xxxxxxxxxxFalseTrue| 目的地 | 超連結 |
|---|---|
| 首頁 | 返回主頁 |
| Python學習 | Python學習 |
| 上一篇 | 15 - 多繼承&多態 |
| 下一篇 | 17 - 文件讀寫 |