python __getattr__ & __setattr__

python中属性查找流程

  1. 对于my_obj.x表达式,首先检查my_obj实例中有没有名为x的实例属性
  2. 如果上一步没找到,检查对应的类中有没有名为x的类属性,因为类属性可以作为实例属性的默认值
  3. 如果上一步没找到,沿着继承树继续查找......
  4. 如果仍找不到,则会调用__getattr__方法。

__getattr__方法

  • __getattr__简单实现
    • self._components是实例属性,现在假设其是一个列表 [0, 1, 2, 3]
    • 如果我们用my_obj.x来调用,在python属性查找流程中,前三步找不到属性x,那么调用__getattr__方法,根据方法中的逻辑,可以返回列表中的第一个元素 0
    • __getattr__方法有两个参数,第一个是self,即实例本身的引用,第二个是属性名的字符串表示形式。
      shortcut_names = 'xyzt'
    
      def __getattr__(self, name):
        cls = type(self) # 获取当前类名Vector
     
        if len(name) == 1: # 属性名只有一个字符,可能是'xyzt'中的某一个
            pos = cls.shortcut_names.find(name) # 查找是否是'xyzt'中的某一个
            if 0 <= pos < len(self._components): # 定位位置
                return self._components[pos]
        msg = '{.__name__!r} object has no attribute {!r}' # 失败则抛出属性错误
        raise AttributeError(msg.format(cls, name))
    
    

__setattr__方法

  • 只使用__getattr__会出现问题,如下:

    1. 通过__getattr__,属性x可以引用到0.0
    2. 更改v.x的值,此时并没有更改原列表中的值,而是创建了一个新的实例属性x
  • 为了在更改__getattr__设置的属性名的时候更改原数据,需要在__setattr__方法里设置具体的行为。

posted @   肖肖凯  阅读(75)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示