天天看點

python中反射之hasattr()、getattr()、setattr()、delattr()函數的使用

原文參考:

https://www.cnblogs.com/cenyu/p/5713686.html

https://www.cnblogs.com/zanjiahaoge666/p/7475225.html

https://blog.csdn.net/longdreams/article/details/78186025

引言:

  在閱讀高手寫的代碼時,有很多簡寫的形式,如果沒有見過還真的看不太懂是什麼意思,其中一個比較常用的就是getattr()用來調用一個類中的變量或者方法,相關聯的hasattr()、getattr()、setattr()函數的使用也一并學習了一下;

正文:

  1. hasattr(object, name)

  判斷object對象中是否存在name屬性,當然對于python的對象而言,屬性包含變量和方法;有則傳回True,沒有則傳回False;需要注意的是name參數是string類型,是以不管是要判斷變量還是方法,其名稱都以字元串形式傳參;getattr和setattr也同樣;

>>> 
>>> class A():
    name = 'python'
    def func(self):
        return 'A()類的方法func()'

    
>>> 
>>> hasattr(A, 'name')
True
>>> 
>>> hasattr(A, 'age')
False
>>> 
>>> hasattr(A, 'func')
True
>>> 
           

2. getattr(object, name, default])

  擷取object對象的屬性的值,如果存在則傳回屬性值,如果不存在分為兩種情況,一種是沒有default參數時,會直接報錯;給定了default參數,若對象本身沒有name屬性,則會傳回給定的default值;如果給定的屬性name是對象的方法,則傳回的是函數對象,需要調用函數對象來獲得函數的傳回值;調用的話就是函數對象後面加括号,如func之于func();

  另外還需要注意,如果給定的方法func()是執行個體函數,則不能寫getattr(A, 'func')(),因為fun()是執行個體函數的話,是不能用A類對象來調用的,應該寫成getattr(A(), 'func')();執行個體函數和類函數的差別可以簡單的了解一下,執行個體函數定義時,直接def func(self):,這樣定義的函數隻能是将類執行個體化後,用類的執行個體化對象來調用;而類函數定義時,需要用@classmethod來裝飾,函數預設的參數一般是cls,類函數可以通過類對象來直接調用,而不需要對類進行執行個體化;

>>> 
>>> class A():
    name = 'python'
    def func(self):
        return 'Hello world'

    
>>> 
>>> getattr(A, 'name')
'python'
>>> 
>>> getattr(A, 'age')    # age變量不存在則報錯

Traceback (most recent call last):
  File "<pyshell#464>", line 1, in <module>
    getattr(A, 'age')
AttributeError: class A has no attribute 'age'
>>> 
>>> getattr(A, 'age', 20)
20
>>> 
>>> getattr(A, 'func')
<unbound method A.func>
>>> 
>>> getattr(A, 'func')()    # func()函數不能被A類對象調用,是以報錯

Traceback (most recent call last):
  File "<pyshell#470>", line 1, in <module>
    getattr(A, 'func')()
TypeError: unbound method func() must be called with A instance as first argument (got nothing instead)
>>> 
>>> getattr(A(), 'func')()
'Hello world'
>>> 

           

>>> class A(object):

    name = 'python'

    @classmethod

    def func(cls):

      return 'the method of A object.'

>>> 

>>> getattr(A, 'func')()

'the method of A object.'

>>>

3. setattr(object, name, value)

  給object對象的name屬性指派value,如果對象原本存在給定的屬性name,則setattr會更改屬性的值為給定的value;如果對象原本不存在屬性name,setattr會在對象中建立屬性,并指派為給定的value;

>>> 
>>> class A():
    name = 'python'
    def func(self):
        return 'Hello world'

    
>>> 
>>> setattr(A, 'name', 'java')
>>> getattr(A, 'name')
'java'
>>> 
>>> setattr(A, 'age', 20)
>>> getattr(A, 'age')
20
>>> 
           

一種綜合的用法是:判斷一個對象的屬性是否存在,若不存在就添加該屬性。

1 >>> class test():
 2 ...     name="xiaohua"
 3 ...     def run(self):
 4 ...             return "HelloWord"
 5 ...
 6 >>> t=test()
 7 >>> getattr(t, "age")    #age屬性不存在
 8 Traceback (most recent call last):
 9   File "<stdin>", line 1, in <module>
10 AttributeError: test instance has no attribute 'age'
11 >>> getattr(t, "age", setattr(t, "age", "18")) #age屬性不存在時,設定該屬性
12 '18'
13 >>> getattr(t, "age")  #可檢測設定成功
14 '18'
15 >>>           

綜合使用的例子:

class Foo(object):

    def __init__(self):
        self.name = "laozhang"

    def func(self):
        return "hello python"

obj = Foo()
#判斷obj中是否有第二個參數
#如果第二個隻是屬性,則傳回屬性值,如果是方法名,則傳回方法的記憶體位址,如果第二個參數沒有在對象中找到,程式崩潰
# res = getattr(obj,"name1") #程式崩潰
# res = getattr(obj,"name") #傳回屬性值 并同時可省略r = res()
res = getattr(obj,"func") #res為func的記憶體位址
r = res()
print(r)

#檢查obj中是否存在func成員,當找到第二個參數時傳回true,否則傳回false
res = hasattr(obj,"func")
print(res)

print(obj.name) #檢視之前obj的name
#設定obj中name為laowang
res = setattr(obj,"name","laowang")
print(obj.name)
#當設定的值不存在時,會自動添加到執行個體對象中
#setattr需要三個參數: x,y,z ==> x.y =z
#相當于obj.age = 10
setattr(obj,"age","10")
print("name=%s,age=%s"%(obj.name,obj.age))  #laowang 10

#删除對象的屬性
delattr(obj,"age")
print("name=%s,age=%s"%(obj.name,obj.age))  #程式崩潰