一文了解Python反射機制(很詳細)

China Soft發表於2024-10-12

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()方法。
SCSS 複製 全屏
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()

相關文章