原文參考:
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)) #程式崩潰