• python中常用的属性访问机制:__getattribute__、__setattr__、__delattr__和__getattr__


    前言

    可以定义object.__getattribute__(self, name)object.__setattr__(self, name, value)object.__delattr__(self, name)object.__getattr__(self, name)方法来自定义对类实例属性访问(x.name 的使用、赋值或删除)

    一、object.__getattribute__(self, name)方法

    1.定义

    此方法会无条件地被调用以实现对类实例属性的访问。如果类还定义了 __getattr__(),则后者不会被调用,除非 __getattribute__() 显式地调用它或是引发了 AttributeError。此方法应当返回属性值或是引发一个 AttributeError 异常。

    2.代码案例

    class MyTest:
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __getattribute__(self, item):
            """
            对象访问属性存在时触发的魔术方法
            :param item: 属性名
            :return: 属性值
            """
            print("获取属性对象(__getattribute__): ", end='')
            return super().__getattribute__(item)
     
    
    m = MyTest('allen', 18)
    
    print(m.name)  # m.name  ===> 本质上触发了:m.__getattribute__('name')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3.代码运行结果

    获取属性对象(__getattribute__): allen
    
    • 1

    二、object.__setattr__(self, name, value)方法

    1.定义

    此方法在一个属性被尝试赋值时被调用。这个调用会取代正常机制(即将值保存到实例字典)。 name 为属性名称, value 为要赋给属性的值。

    2.代码案例

    class MyTest:
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __setattr__(self, key, value):
            """
            对象设置属性触发的魔术方法
            :param key: 属性名
            :param value: 属性值
            :return:
            """
            print(f"设置属性值(__setattr__):{key}:{value}")
            super().__setattr__(key, value)
    
    
    m = MyTest('allen', 18)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3.代码运行结果

    设置属性值(__setattr__):name:allen
    设置属性值(__setattr__):age:18
    
    • 1
    • 2

    三、object.__delattr__(self, name)方法

    1.定义

    类似于 setattr() 但其作用为删除而非赋值。此方法应该仅在 del obj.name 对于该对象有意义时才被实现。

    2.代码案例

    class MyTest:
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __delattr__(self, item):
            """
            删除对象属性触发的魔术方法
            :param item: 要删除的属性名
            :return:
            """
            print(f"删除属性(__delattr__):{item}")
            super().__delattr__(item)
    
    
    m = MyTest('allen', 18)
    
    print("删除前,属性字典:", m.__dict__)
    del m.name
    print("删除后,属性字典:", m.__dict__)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3.代码运行结果

    删除前,属性字典: {'name': 'allen', 'age': 18}
    删除属性(__delattr__):name
    删除后,属性字典: {'age': 18}
    
    • 1
    • 2
    • 3

    四、object.__getattr__(self, name)方法

    1.定义

    当默认属性访问因引发 AttributeError 而失败时被调用 (可能是调用 getattribute() 时由于 name 不是一个实例属性或 self 的类关系树中的属性而引发了 AttributeError;或者是对 name 特性属性调用 get() 时引发了 AttributeError)。此方法应当返回属性值或是引发一个 AttributeError 异常。

    请注意如果属性是通过正常机制找到的,getattr() 就不会被调用。(这是在 getattr() 和 setattr() 之间故意设置的不对称性。)这既是出于效率理由也是因为不这样设置的话 getattr() 将无法访问实例的其他属性。要注意至少对于实例变量来说,你不必在实例属性字典中插入任何值(而是通过插入到其他对象)就可以模拟对它的完全控制。

    2.代码案例

    class MyTest:
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __getattribute__(self, item):
            """
            对象访问属性存在时触发的魔术方法
            :param item: 属性名
            :return: 属性值
            """
            print("获取属性对象(__getattribute__): ", end='')
            return super().__getattribute__(item)
    
        def __getattr__(self, item):
            """
            对象获取属性,属性不存在时触发的魔术方法
            :param item:
            :return:
            """
            print("获取属性对象(__getattr__): ", end='')
            return
    
    
    m = MyTest('allen', 18)
    
    print(m.sex)  # 属性不存在,先调用__getattribute__,再调用__getattr__,返回None
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    3.代码运行结果

    获取属性对象(__getattribute__): 获取属性对象(__getattr__): None
    
    • 1
  • 相关阅读:
    哈工大-公差基础-配合(互换性和测量基础)-3
    C# tcp通信连接正常判断
    Zygisk-IL2CppDumper对抗方案
    mybatis 01: 静态代理 + jdk动态代理 + cglib动态代理
    HEC-RAS 1D/2D水动力与水环境模拟教程
    卷积神经网络 作业
    nginx部署多个前端项目
    linux内核调试工具之kprobe(二)
    K8S 控制器 service ingress
    java毕业设计哈尔滨文旅信息网站mybatis+源码+调试部署+系统+数据库+lw
  • 原文地址:https://blog.csdn.net/weixin_39033358/article/details/131149508