python3:很簡單但經典例子介紹__getattr__ 魔法函式。
阿新 • • 發佈:2018-11-09
這個魔法函式的意義是 當例項化物件呼叫屬性不存在的時候再呼叫,】
如果不重寫這個函式 系統就報錯,說明系統最後的兜底工作。
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 也是同樣的原理。