这个魔法函数的意义是 当实例化对象调用属性不存在的时候再调用,】
如果不重写这个函数 系统就报错,说明系统最后的兜底工作。
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 也是同样的原理。