Python基礎-21反射

21 反射

21.1 反射概念

    反射主要是指程序能夠訪問、檢測和修改其自己狀態或行爲的一種能力。在Python中最重要的4個方法以下所示:html

  • getattr:獲取指定字符串名稱的對象屬性
  • setattr:給對象添加類屬性
  • hasattr:判斷對象是否存在某個對應的對象
  • delattr:刪除指定的屬性

    咱們先來定義一個類,以下所示:python

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類爲例app

# 實例化一個類
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類型,無論是判斷類屬性仍是類方法,其名稱均以字符串形式傳參ui

    示例以下所示:code

# 實例化一個類
apple=Fruit("apple","red")
# 爲實例添加一個類屬性,並設置其值
setattr(apple,"destination","china")
print(f'第一次添加類屬性,其值爲(添加操做):{getattr(apple,"destination")}')
setattr(apple,"destination","USA")
print(f'第二次添加類屬性,其值爲(更新操做):{getattr(apple,"destination")}')

輸出結果以下所示:htm

第一次添加類屬性,其值爲(添加操做):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
輸入的模塊不存在

兩種方法一對比,天然就以爲方法二更簡潔,也更容易維護,更不用擔憂類中有不少個方法。

本文地址:http://www.javashuo.com/article/p-sosyssjy-bq.html

本文同步在微信訂閱號上發佈,如各位小夥伴們喜歡個人文章,也能夠關注個人微信訂閱號:woaitest,或掃描下面的二維碼添加關注:
MyQRCode.jpg

相關文章
相關標籤/搜索