关于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__ 同时出现
posted @ 2020-03-30 11:22  binger0712  阅读(394)  评论(0编辑  收藏  举报