自定义属性访问__getattribute__/设置__setattr__/删除__delattr__方法

目录

1.object.__getattr__

        当属性查找没有找到的时候(报错AttriErro)时,会触发此方法

2.object.__getattribute__

        当查找属性时,第一时间会调用此方法

3.object.__setattr__

        设置属性时,会触发此方法设置属性

4.object.__delattr__

        在del 对象属性时,会触发此方法


定义魔术方法来自定义类实例的属性访问。

总结:当父类的方法不能满足自己的功能需求时,可以重写父类方法,重写时把想要增加的功能添加上后,通过super().父类方法()来扩展父类方法的功能,这样,自己重写的方法,既有了父类方法的功能,又有了自己添加的功能。

1.object.__getattr__

        当属性查找没有找到的时候(报错AttriErro)时,会触发此方法

class Attr:

    def __getattr__(self, item):
        # 当访问对象属性的时候,如果该属性不存在,并且报错AttrError时,此方法被触发。
        print('---getattr---方法触发了')
        return 666


if __name__ == '__main__':
    a = Attr()
    print(a.name)
    # 输出:
    # ---getattr - --方法触发了
    # 666

2.object.__getattribute__

        当查找属性时,第一时间会调用此方法

class Attr:

    def __getattr__(self, item):
        # 当访问对象属性的时候,如果该属性不存在,并且报错AttrError时,此方法被触发。
        print('---getattr---方法触发了')
        # 触发时调用父类的getattribute方法,查找属性,如果没找到,抛出 AttributeError: 'Attr' object has no attribute 'name'
        object.__getattribute__(self, item)


    def __getattribute__(self, item):
        # 访问属性时,会第一时间触发此方法查找属性
        print('---getattribute---方法触发了')

        # 增加自定义功能
        print('此处增加了自定义功能')

        # 增加了自定义功能后,调用父类的getattribute方法查找属性
        return super().__getattribute__(item)



if __name__ == '__main__':
    a = Attr()
    a.name = '春田'
    print(a.name)
    # 输出:
    ---getattribute - --方法触发了
    此处增加了自定义功能
    春田

3.object.__setattr__

        设置属性时,会触发此方法设置属性

class Attr:

    def __setattr__(self, key, value):
        # 在给对象设置属性的时候,会触发此方法
        print('---setattr---方法触发了')
        print(key)
        print(value)


if __name__ == '__main__':
    a = Attr()
    a.name = '春田'
    # 输出:
    ---setattr - --方法触发了
    name
    春田
class Attr:

    def __setattr__(self, key, value):
        # 在给对象设置属性的时候,会触发此方法
        print('---setattr---方法触发了')
        if key == 'name':
            # 锁死对象的name属性,无法被对象外部修改,不管外部a.name设置为多少,name属性始终不会被修改
            super().__setattr__(key, "羊咩咩")
        else:
            # 设置的对象属性不是name,就可正常修改
            super().__setattr__(key, value)


if __name__ == '__main__':
    a = Attr()
    a.name = '春田'
    print(a.name)
    a.age = 130
    print(a.age)
    # 输出:
    ---setattr - --方法触发了
    羊咩咩
    ---setattr - --方法触发了
    130

4.object.__delattr__

        在del 对象属性时,会触发此方法

class Attr:

    def __delattr__(self, item):
        # 删除属性的时候会触发此方法
        print('---delattr---方法触发了')


if __name__ == '__main__':
    a = Attr()
    a.name = '春田'
    del a.name
    # 输出:
    ---delattr - --方法触发了
class Attr:

    def __delattr__(self, item):
        # 删除属性的时候会触发此方法
        print('---delattr---方法触发了')
        # 扩展功能
        print('此处是扩展的功能')
        # 调用父类的delattr方法删除属性
        super().__delattr__(item)
        print(f'属性{item}已经被删除了')


if __name__ == '__main__':
    a = Attr()
    a.name = '春田'
    del a.name
    print(a.name)
    # 输出:
    ---delattr - --方法触发了
    此处是扩展的功能
    属性name已经被删除了
    AttributeError: 'Attr' object has no attribute 'name'
class Attr:

    def __delattr__(self, item):
        # 删除属性的时候会触发此方法
        print('---delattr---方法触发了')
        # 扩展功能,如果想删除的属性是name,就拒绝,不能删除
        if item == 'name':
            print(f'{item}属性不允许删除')    # 保护name属性不会被删除
        else:
            # 调用父类的delattr方法删除属性
            super().__delattr__(item)
            print(f'属性{item}已经被删除了')


if __name__ == '__main__':
    a = Attr()
    a.name = '春田'
    del a.name
    print(a.name)
    # 输出:
    ---delattr - --方法触发了
    name属性不允许删除
    春田

你可能感兴趣的:(Python细节,python,属性访问,数据和自省)