1. 程式人生 > >python3:很簡單但經典例子介紹__getattr__ 魔法函式。

python3:很簡單但經典例子介紹__getattr__ 魔法函式。

這個魔法函式的意義是 當例項化物件呼叫屬性不存在的時候再呼叫,】
如果不重寫這個函式 系統就報錯,說明系統最後的兜底工作。

class A:
    def __init__(self):
        pass

a=A()

print(a.age)

列印結果:

AttributeError: 'A' object has no attribute 'age'

這個情況下我們就可以應用 getattr 這個魔法函式。

class A:
    def __init__(self):
        pass
    def __getattr__(self, item):
        print("即使你沒有屬性也不會報錯")

a=A()

print(a.age)

列印結果:

即使你沒有屬性也不會報錯
None

現在開始我們的經典的例子如下 :

class ObjectDict(dict):
    def __init__(self, *args, **kwargs):    
        super(ObjectDict, self).__init__(*args, **kwargs)  
    def __getattr__(self, name):
        value =  self[name]
        if isinstance(value, dict):
            value = ObjectDict(value)
        return value

if __name__ == '__main__':
    od = ObjectDict(asf={'a': 1}, d=True)
    print od.asf, od.asf.a     # {'a': 1} 1
    print od.d                 # True  

解讀要點 如下 :

**1. Python程式碼中func(*args, kwargs)是什麼意思
*args表示任何多個無名引數,它是一個tuple

**kwargs表示關鍵字引數,它是一個dict
 測試程式碼如下:
def foo(*args,**kwargs):
      print 'args=',args
       print 'kwargs=',kwargs
       print '**********************'
if __name__=='__main__':
foo(1,2,3)
foo(a=1,b=2,c=3)
foo(1,2,3,a=1,b=2,c=3)
foo(1,'b','c',a=1,b='b',c='c')

執行結果如下:

args= (1, 2, 3)
kwargs= {}
**********************
args= ()
kwargs= {'a': 1, 'c': 3, 'b': 2}
**********************
args= (1, 2, 3)
kwargs= {'a': 1, 'c': 3, 'b': 2}
**********************
args= (1, 'b', 'c')
kwargs= {'a': 1, 'c': 'c', 'b': 'b'}
**********************

2. 為什麼要繼承dict
要翻看dict 類原始碼 有如下的描述:

class dict(object):
   """
   dict(**kwargs) -> new dictionary initialized with the name=value pairs
       in the keyword argument list.  For example:  dict(one=1, two=2)

od = ObjectDict(asf={‘a’: 1}, d=True)
可以解讀為 {“asf”:{‘a’: 1},“d”:True}
3. 執行getattr
od.asf 是找不到這個屬性,直接執行 getattr
把asf 當作引數name 進行傳遞給
value = od[asf]
通過在 {“asf”:{‘a’: 1},“d”:True} 是可以找到匹配值{‘a’: 1}
進行return ,所以od.asf可以列印 {‘a’: 1},
od.asf.a 再去走了一次迴圈 呼叫了if 語句走了 value = ObjectDict(value)
最終返回 1
od.d 也是同樣的原理。