浅谈__getattribute__与__getattr__【转】
首先我们看看如何访问一个对象的属性:
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
如果我们想改变访问属性的逻辑,如执行a.age
语句并非返回18,而是返回问年龄是不礼貌的行为。这里就可以用__getattribute__方法拦截属性,实现我们想要实现的逻辑
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
事实上,在实例化的对象进行.
操作的时候(形如:a.xxx/a.xxx()
),都会自动去调用__getattribute__方法。但是,如果某个属性在__getattribute__方法中未能找到,此时会调用__getattr__方法。
如我们访问对象a中不存在的属性,会得到异常。比方执行print(a.NAME)
语句,运行结果如下:AttributeError: 'A' object has no attribute 'NAME'
但我就想无论是a.NAME
,a.Name
,还是a.NaME
等等,即n a m e
(包含大小写)四个元素组成的属性,访问结果都同a.name
一样,可以做如下处理:
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
总结:
1.__getattribute__
方法优先级比__getattr__
高
2.只有在__getattribute__
方法中找不到对应的属性时,才会调用__getattr__
3.如果是对不存在的属性做处理,尽量把逻辑写在__getattr__
方法中
4.如果非得重写__getattribute__
方法,需要注意两点:第一是避免.
操作带来的死循环;第二是不要遗忘父类的__getattribute__
方法在子类中起的作用