关于Python特殊方法(__getattr__, __setattr__, __getattribute__)总结
- __getattr__ :获取属性值,经常与 __setattr__, __delattr__ 配合对属性方法封装管理
- 触发条件:访问对象的属性,且在属性不存在触发(AttributeError)异常时
- 例子:
class Student(object): def __init__(self, name, alias): self.name = name self.alias = alias def __getattr__(self, item): print("获取不存在的属性:item:", item) return self.__dict__.get(item, None) obj = Student("binger", "binger1") print("name:", obj.name) print("age:", obj.age) # 结果-----------------> # => binger # => 获取不存在的属性:item: age # => None class Student2(object): def __init__(self, name, alias): self.name = name self.alias = alias obj = Student2("binger", "binger1") print("name:", obj.name) print("age:", obj.age) # 结果----------------> # name: binger # Traceback (most recent call last): # File "/Users/shujun/self/logger_app/check3.py", line 29, in <module> # print("age:", obj.age) # AttributeError: 'Student2' object has no attribute 'age'
可以实现,在获取不存在的属性是的,实现特定的处理
- 特点:
- 只有调用的属性不存在
- 避免书写过于复杂的处理,避免调用本实例的方法,以免属性不存在,出现无限循环
- __setattr__ : 为属性赋值
- 触发条件:为属性赋值
- 例子:
class Student3(object): def __init__(self, name, alias): self.name = name self.alias = alias def __setattr__(self, key, value): print("赋值:setattr: ", key, value) super().__setattr__(key, value) # 二者在一定在不存在 __getattrbute__ 时,效果是一样的 # self.__dict__[key] = value stu = Student3(name="binger", alias="binger2") print(stu.__dict__) # 结果--------------> # 赋值:setattr: name binger # 赋值:setattr: alias binger2 # {'name': 'binger', 'alias': 'binger2'}
- 特点:
- 每次赋值,不管原属性值是否存在
- 避免书写过于复杂的处理,避免调用过程中,给本实例的其他属性赋值,以免出现无限循环,可以考虑使用 self.__dict__ 或者super 形式
- self.__dict__[key] = : __dict__属性是一个字典,所有的实例属性都存储在这个字典中,而修改__dict__字典中的键值对不会触发__setattr__方法,如果同时定义了__getattribute__方法,那么在修改__dict__字典中的键值对时,由于调用了self.__dict__属性,同样会触发__getattribute__方法,此时不得已使用时建议使用 supper 方式
- supper 调用父类方法实现
- __getattrbute__ : 获取属性值
- 触发条件:在每次调用实例的属性时,不管调用普通还是特殊属性,均会触发
- 实例:
-
class Student4(object): def __init__(self, name, alias): self.name = name self.alias = alias def __getattribute__(self, item): print("调用属性:", item) return super().__getattribute__(item) # return self.__dict__[item] # 不能使用,否则会出现死循环 stu = Student4(name="binger", alias="binger2") print("name: ", stu.name) # 结果--------------> # 调用属性: name # name: binger
- 特点:
- 每次调用不管属性,均会执行,属性不存在跑出 AttributeError 异常
- 要求使用 supper 避免死循环
- 为避免可能出现死循环,请避免和 __setattr__ 同时出现