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')

3.代码运行结果

获取属性对象(__getattribute__): allen

二、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)

3.代码运行结果

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

三、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__)

3.代码运行结果

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

四、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

3.代码运行结果

获取属性对象(__getattribute__): 获取属性对象(__getattr__): None

你可能感兴趣的:(python测试开发,python,开发语言,算法)