https://blog.csdn.net/weixin_40025666/article/details/134456717
https://www.cnblogs.com/mengdie1978/p/17425581.html
一、反射的概念
python的反射機制,核心就是利用字串去已存在的模組中找到指定的屬性或方法,找到方法後自動執行——基於字串的事件驅動。
二、熟悉物件導向的屬性方法
- hasattr(object,'attrName'):判斷該物件是否有指定名字的屬性或方法,返回值是bool型別
- setattr(object,'attrName',value):給指定的物件新增屬性以及屬性值
- getattr(object,'attrName'):獲取物件指定名稱的屬性或方法,返回值是str型別
- delattr(object,'attrName'):刪除物件指定名稱的屬性或方法值,無返回值
class Fruit:
# 構造方法
def __init__(self,name,color):
self.name = name
self.color = color
# 類的普通方法
def buy(self,price,num):
print("水果的價格是:",price*num)
"""
hasattr(object,'attrName'):判斷該物件是否有指定名字的屬性或方法,返回值是bool型別
setattr(object,'attrName',value):給指定的物件新增屬性以及屬性值
getattr(object,'attrName'):獲取物件指定名稱的屬性或方法,返回值是str型別
delattr(object,'attrName'):刪除物件指定名稱的屬性或方法值,無返回值
"""
apple = Fruit("蘋果","紅色")
print(hasattr(apple,'name')) # 判斷物件是否有該屬性或方法
print(hasattr(apple,'buy'))
# 獲取物件指定的屬性值
print(getattr(apple,'name'))
print(apple.name)
f = getattr(apple,'buy')
f(5,10)
# 設定物件對應的屬性
setattr(apple,'weight',100)
# 刪除物件對應的屬性
delattr(apple,'name')
print(hasattr(apple,'name'))
注:getattr,hasattr,setattr,delattr對模組的修改都在記憶體中進行,並不會影響檔案中真實內容
三、物件導向的反射機制
需求描述:使用者透過輸入字串來呼叫物件的對應方法,透過模擬一個伺服器響應使用者的請求,設定有註冊頁、登入頁、主頁、關於頁以及錯誤頁。
class WebSite:
def register(self):
print("歡迎來到註冊頁面")
def login(self):
print("歡迎來到登入頁面")
def home(self):
print("歡迎進入主頁")
def about(self):
print("關於我們")
def error(self):
print("404 No Found!")
page = WebSite()
while True:
choose = input("請輸入你要進入的頁面>>>")
if choose == 'register':
page.register()
elif choose == 'login':
page.login()
elif choose == 'home':
page.home()
elif choose == 'about':
page.about()
else:
page.error()
由於程式碼段對使用者的請求頁判斷的程式碼塊冗長,並且當新增一個網頁時也要實時修改對應的主體程式碼,維護起來不方便。
class WebSite:
def register(self):
print("歡迎來到註冊頁面")
def login(self):
print("歡迎來到登入頁面")
def home(self):
print("歡迎進入主頁")
def about(self):
print("關於我們")
def error(self):
print("404 No Found!")
page = WebSite()
while True:
choose = input("請輸入你要進入的頁面>>>")
# 反射機制實現上述功能,最佳化程式碼結構
if hasattr(page,choose):
f = getattr(page,choose)
else:
page.error()
透過應用物件導向操作屬性的方法很好的解決了這個問題,這就是反射機制。Python物件導向中的反射:透過字串的形式操作物件相關的屬性。
四、例項應用
在正式介紹實際web開發中的應用場景之前,先來看看這樣的一個模組。
# 模組:importlib
import importlib
res = 'myfile.b'
# 傳入字串路徑,呼叫importlib類,實現 from myfile import b
ret = importlib.import_module(res)
# 該方法最小隻能到.py檔名即模組
print(ret)
是的,稍微閱讀一下上面的例項程式碼就可以知道importlib
模組的功能是:即安裝字串式的路徑自動匯入模組,呼叫importlib.import_module()
方法,但該方法的最小粒度只能達到.py檔名
即模組。
需求描述:輸入多層的模組路徑,自動生成物件並呼叫該類的方法。比如:notify.email.Email,notify包下面有模組email,模組email中包括了Email類,利用該類宣告物件,並呼叫其中的send()方法。
import importlib
#'notify.email.Email'
path_str = input("請輸入包-模組-類的字串路徑:")
module_path,class_name = path_str.rsplit('.',maxsplit=1)
# 1 利用字串匯入模組
module = importlib.import_module(module_path) # from notify import email
# 2 利用反射獲取類名
cls = getattr(module,class_name) # Email、QQ、Wechat
# 3 生成類的物件
obj = cls()
# 4 直接呼叫send方法
obj.send()