python __getattr__()、__call__

__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)

這實際上可以把一個類的所有屬性和方法調用全部動態化處理了,不需要任何特殊手段。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章