__getattr__()方法 |
正常情況下,當我們調用類的方法或者屬性時,如果搜索不到對應的方法或者屬性,就會報錯。
>>> class Student(object):
... def __init__(self):
... self.name = 'Micheal'
...
>>> s = Student()
>>> print s.name
Micheal
>>> print s.score
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'
要避免這個錯誤,除了可以加上一個score屬性外,python還有另外一個機制,那就是重寫一個__getattr__()方法,動態返回一個屬性。
class Student(object):
def __init__(self):
self.name = 'Michael'
def __getattr__(self, attr):
if attr=='score':
return 99
當調用不存在的屬性的時候,比如score,python解釋器就會調用__getattr__(self, 'score')
來嘗試獲得屬性。
注意:這裏自動把不存在的屬性轉換爲了字符串的形式,然後傳到函數__getattr__(self,attr)__
中,並賦值給attr,所以這是的attr是一個字符串。
>>> s = Student()
>>> s.name
'Michael'
>>> s.score
99
返回函數也是完全可以的:
class Student(object):
def __getattr__(self, attr):
if attr=='age':
return lambda: 25
只是調用方式要變爲,因爲返回的是一個函數對象(類似函數指針)
>>> s.age()
25
注意,只有在沒有找到屬性的情況下,才調用__getattr__
,已有的屬性,比如name,不會在__getattr__
中查找。
此外,注意到任意調用如s.abc都會返回None,這是因爲我們定義的__getattr__
默認返回就是None。要讓class只響應特定的幾個屬性,我們就要按照約定,拋出AttributeError的錯誤:
class Student(object):
def __getattr__(self, attr):
if attr=='age':
return lambda: 25
raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
這實際上可以把一個類的所有屬性和方法調用全部動態化處理了,不需要任何特殊手段。