python的easyDict库,是一个属性调用友好库
python中对象属性的获取链
在使用obj.value时,python内部执行顺序如下:
obj.value等价于getattr(obj,'value'),会调用基类object Python默认的__getattribute__方法,该方法逻辑如下:
最开始,python会使用obj.__dict__[value]的方法查找,也就是查找对象内置字典的key值
如果上述方法查找不到,会使用type(obj).__dict__[value]来查找,也就会查找obj类的属性
如果上述方法查找不到,python会用mro的查找方法遍历type(obj)的基类,在其基类中查找类属性,知道找到位置
如果还是找不到,__getattribute__在抛出AttributeError前会调用__getattr__方法
内置方法__getattr__
如果我们在类中定义了__getattr__方法,当使用正常的逻辑访问属性(如:obj.a)而找不到该属性时,就会调用这个__getattr__方法。
内置方法__getattribute__
之前所说的查找方式为默认的Python的调用逻辑,当在类内定义了__getattribute__方法,就会打破原有属性查找方式,在obj.value查找属性时,会无条件条用__getattribute__方法。
使用归纳:
1.__getattribute__方法优先级比__getattr__高
2.只有在__getattribute__方法中找不到对应的属性时,才会调用__getattr__
3.如果是对不存在的属性做处理,尽量把逻辑写在__getattr__方法中
4.如果非得重写__getattribute__方法,需要注意两点:第一是避免.操作带来的死循环;第二是不要遗忘父类的__getattribute__方法在子类中起的作用
实例一:
class A(object):
def __init__(self):
self.name = "Bob"
self.age = 18
self.gender = "male"
if __name__ == "__main__":
a = A()
print(a.name)
print(a.age)
print(a.gender)
输出结果:
Bob
18
male
实例二:存在__getattribute__时,调用已存在的属性,直接调用__getattribute__
# -*- coding:utf-8 -*-
# coding=utf-8
class A(object):
def __init__(self):
self.name = "Bob"
self.age = 18
self.gender = "male"
def __getattribute__(self, attr): # 拦截age属性
if attr == "age":
return "问年龄是不礼貌的行为" # 非age属性执行默认操作
else:
return object.__getattribute__(self, attr)
if __name__ == "__main__":
a = A()
print(a.age)
print(a.name)
print(a.gender)
输出结果:
问年龄是不礼貌的行为
Bob
male
实例三:属性不存时,存在__getattr__,则调用__getattr__
# -*- coding:utf-8 -*-
# coding=utf-8
class A(object):
def __init__(self):
self.name = "Bob"
self.age = 18
self.gender = "male"
def __getattr__(self, attr):
return eval("self."+attr.lower()) #即:再次去执行__getattribute__方法
if __name__ == "__main__":
a = A()
print("a.name -> {}".format(a.name))
print("a.NAME -> {}".format(a.NAME))
print("a.Name -> {}".format(a.Name))
print("a.NaME -> {}".format(a.NaME))
输出结果:
a.name ->Bob
a.NAME ->Bob
a.Name ->Bob
a.NaME ->Bob