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__()
實現(常用、重點)❗ 當實例化不同對象的時候,內存地址會發生變化
xxxxxxxxxx
class A(object):
pass
a1 = A()
print(a1)
a2 = A()
print(a2)
輸出結果:
xxxxxxxxxx
<__main__.A object at 0x102467e50>
<__main__.A object at 0x102467ed0>
👉🏻 內存地址發生變化,說明是不同的對象
💡 實現單例模式,對象的內存地址都會是一樣的,只有一個對象
💡 設計流程:
定義一個類屬性,初始值為None,用來記錄單例對象的引用
重寫__new__()
方法
進行判斷,如果類屬性是None,把__new__()
返回的對象引用保存進去
返回類屬性中記錄的對象引用
xxxxxxxxxx
class 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}')
# 單例模式:每一次實例化所創建的對象都是同一個,內存地址都一樣
輸出結果:
xxxxxxxxxx
This 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,並輸入:
xxxxxxxxxx
class Test(object):
def test(self):
print('test')
te =Test()
然後在本文件運行以下代碼:
xxxxxxxxxx
from pytest3 import te as te01
from pytest3 import te as te02
print(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__()
xxxxxxxxxx
class Person(object):
"""Person類的描述信息"""
pass
print(Person.__doc__)
輸出結果:
xxxxxxxxxx
Person類的描述信息
__module__()
和__class__()
在當前文件夾建立pytest3.py,並輸入:
xxxxxxxxxx
class B:
def func1(self):
print('laugh')
然後在本文件運行以下代碼:
xxxxxxxxxx
import pytest3
b = pytest3.B()
print(b.__module__)
print(b.__class__)
輸出結果:
xxxxxxxxxx
pytest3
<class 'pytest3.B'>
__str__()
:對象的描述信息💡 如果類中定義了此方法,那麼在打印對象時,默認輸出該方法的返回值,即打印方法中return的數據
❗ 注意:__str__()
必須返回一個字符串
xxxxxxxxxx
class C:
def __str__(self):
return '這裡是str的返回值' # 必須要有返回值,並且必須為字符串類型
c = C()
print(c)
輸出結果:
xxxxxxxxxx
這裡是str的返回值
__call__()
:使一個實例對象成為一個「可調用對象」,像函數那樣可以調用可調用對象:凡是可以把一對()應用到某個對象上,都可以被稱為可調用對象
例子:函數、內置函數、類
callable():判斷一個對象是否可調用對象
xxxxxxxxxx
def func():
print('laugh')
print(callable(func)) # 返回True,是可調用對象
name = 'Amy'
print(callable(name)) # 返回False,不是可調用對象
輸出結果:
xxxxxxxxxx
True
False
xxxxxxxxxx
class A:
pass
a = A()
print(callable(a))
class B:
def __call__(self):
print('This is __call__()')
b = B() # 調用一個可調用的實例對象,其實就是在調用它的__call__()方法
print(callable(b))
輸出結果:
xxxxxxxxxx
False
True
目的地 | 超連結 |
---|---|
首頁 | 返回主頁 |
Python學習 | Python學習 |
上一篇 | 15 - 多繼承&多態 |
下一篇 | 17 - 文件讀寫 |