21 反射 21.1 反射概念 反射主要是指程式可以訪問、檢測和修改其本身狀態或行為的一種能力。在Python中最重要的4個方法如下所示: getattr:獲取指定字元串名稱的對象屬性 setattr:給對象添加類屬性 hasattr:判斷對象是否存在某個對應的對象 delattr:刪除指定的屬性 ...
21 反射
21.1 反射概念
反射主要是指程式可以訪問、檢測和修改其本身狀態或行為的一種能力。在Python中最重要的4個方法如下所示:
- getattr:獲取指定字元串名稱的對象屬性
- setattr:給對象添加類屬性
- hasattr:判斷對象是否存在某個對應的對象
- delattr:刪除指定的屬性
我們先來定義一個類,如下所示:
class Fruit:
def __init__(self,name,color):
self.name=name
self.color=color
def __str__(self):
return f"Fruit is {self.name} color is {self.color}"
def buy(self,price,totalWeight):
return f"Fruit is {self.name},total price is {price*totalWeight}"
21.2 反射常用方法
21.2.1 getattr
getattr主要用來獲取指定字元串名稱的對象屬性,其使用方法如下所示:
getattr(object, name:string[, default]) -> value
- name參數需要為string類型,不管是判斷類屬性還是類方法,其名稱均以字元串形式傳參
- 如果屬性存在,則返回其屬性值,不存在則分為兩種情況,一種是沒有default參數時,則直接報錯,如給定了default參數,對象沒有其屬性,則返回給定的default值
- 如果獲取的是類方法,則返回函數對象
以前面定義的Fruit類為例
# 實例化一個類
apple=Fruit("apple","red")
# 利用反射獲取類屬性
print(getattr(apple,"name"))
print(getattr(apple,"color"))
# 利用反射獲取類方法
print(getattr(apple,"buy"))
# 利用反射獲取不存在的屬性且有預設值
print(getattr(apple,"test","123"))
# 利用反射獲取不存在的屬性且沒有預設值 - 報錯
print(getattr(apple,"test"))
輸出結果如下所示:
apple
red
<bound method Fruit.buy of <__main__.Fruit object at 0x000001E70B356288>>
123
Traceback (most recent call last):
File "C:/Users/Surpass/Documents/PycharmProjects/SADCI/TempCode/reflectorSample.py", line 24, in <module>
print(getattr(apple,"test"))
AttributeError: 'Fruit' object has no attribute 'test'
21.2.2 setattr
setattr主要用於給對象添加一個類屬性,如果添加的屬性已經存在,則對其進行更新,否則則進行創建,其使用方法如下所示:
setattr(object, name:string, value)
name參數需要為string類型,不管是判斷類屬性還是類方法,其名稱均以字元串形式傳參
示例如下所示:
# 實例化一個類
apple=Fruit("apple","red")
# 為實例添加一個類屬性,並設置其值
setattr(apple,"destination","china")
print(f'第一次添加類屬性,其值為(添加操作):{getattr(apple,"destination")}')
setattr(apple,"destination","USA")
print(f'第二次添加類屬性,其值為(更新操作):{getattr(apple,"destination")}')
輸出結果如下所示:
第一次添加類屬性,其值為(添加操作):china
第二次添加類屬性,其值為(更新操作):USA
21.2.3 hasattr
hasattr常用於判斷對象中是否存在其屬性或方法,常用用法如下所示:
hasattr(object, name:string) -> bool
name參數需要為string類型,不管是判斷類屬性還是類方法,其名稱均以字元串形式傳參
示例如下所示:
# 實例化一個類
apple=Fruit("apple","red")
# 判斷屬性或方法是否存在
print(f'對象是否存在其屬性 name - {True if hasattr(apple,"name") else False }')
print(f'對象是否存在其屬性 country - {True if hasattr(apple,"country") else False }')
print(f'對象是否存在其方法 buy - {True if hasattr(apple,"buy") else False }')
輸出結果如下所示:
對象是否存在其屬性 name - True
對象是否存在其屬性 country - False
對象是否存在其方法 buy - True
21.2.4 delattr
delattr常用於刪除指定的屬性,但不能用於方法,常用用法如下所示:
delattr(object, name:string)
name參數需要為string類型,不管是判斷類屬性還是類方法,其名稱均以字元串形式傳參
示例如下所示:
# 實例化一個類
apple=Fruit("apple","red")
delattr(apple,"name")
# 判斷屬性或方法是否存在
print(f'對象是否存在其屬性 name - {True if hasattr(apple,"name") else False }')
print(f'對象是否存在其屬性 country - {True if hasattr(apple,"country") else False }')
print(f'對象是否存在其方法 buy - {True if hasattr(apple,"buy") else False }')
輸出結果如下所示:
對象是否存在其屬性 name - False
對象是否存在其屬性 country - False
對象是否存在其方法 buy - True
在日常使用,一般會進行判斷屬性是否存在,然後再調用獲取、添加和刪除方法
21.3 示例
以下用一個簡單的示例來解釋,反射在實際的應用案例。現在有一個場景,就是根據傳入的不同的模塊名稱,調用不同的模塊所對應方法,代碼如下所示:
class ReflectSample:
def moduleA(self):
print("我是moduleA")
def moduleB(self):
print("我是moduleB")
def moduleC(self):
print("我是moduleC")
def moduleD(self):
print("我是moduleD")
- 方法一:
while True:
reflectSample=ReflectSample()
choice=input("請輸入模塊名稱")
if choice == "moduleA":
reflectSample.moduleA()
elif choice == "moduleB":
reflectSample.moduleB()
elif choice == "moduleC":
reflectSample.moduleC()
elif choice == "moduleD":
reflectSample.moduleD()
else:
print("輸入的模塊不存在")
測試結果如下所示:
請輸入模塊名稱moduleA
我是moduleA
請輸入模塊名稱moduleD
我是moduleD
請輸入模塊名稱moduleF
輸入的模塊不存在
- 方法二:
while True:
reflectSample = ReflectSample()
choice = input("請輸入模塊名稱")
if hasattr(reflectSample,choice):
func=getattr(reflectSample,choice)
func()
else:
print("輸入的模塊不存在")
測試結果如下所示:
請輸入模塊名稱moduleA
我是moduleA
請輸入模塊名稱moduleD
我是moduleD
請輸入模塊名稱moduleF
輸入的模塊不存在
兩種方法一對比,自然就覺得方法二更簡潔,也更容易維護,更不用擔心類中有很多個方法。
本文地址:https://www.cnblogs.com/surpassme/p/12902742.html
本文同步在微信訂閱號上發佈,如各位小伙伴們喜歡我的文章,也可以關註我的微信訂閱號:woaitest,或掃描下麵的二維碼添加關註: