python定制自定义属性访问之__getattr__, __getattribute__

1,官方文档摘要

可以定义下列方法来自定义对类实例属性访问(x.name 的使用、赋值或删除)的具体含义.

object.__getattr__(selfname)

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

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

object.__getattribute__(selfname)

此方法会无条件地被调用以实现对类实例属性的访问。如果类还定义了 __getattr__(),则后者不会被调用,除非 __getattribute__() 显式地调用它或是引发了 AttributeError。此方法应当返回(找到的)属性值或是引发一个 AttributeError 异常。为了避免此方法中的无限递归,其实现应该总是调用具有相同名称的基类方法来访问它所需要的任何属性,例如 object.__getattribute__(self, name)

2,代码演示

class A:
    """定制属性"""
    x = 10

    def __init__(self, name, age):
        self.name = name
        self.age = age

    """
    如果访问的属性存在,就不会调用__getattr__方法。这个属性的存在,包括类属性和实例属性。
    如果访问的属性不存在,才会调用此方法,可以给不存在属性设置默认值等操作
    """
    def __getattr__(self, item):
        print('--getattr--')
        if item == 'tall':
            print('180cm')
        else:
            raise AttributeError('无此属性')


a = A('jack', 23)
print(a.x)
print(a.name)
print(a.tall) # __getattr__方法无返回值所以print结果为None
print(a.y)


执行结果:

10
jack
--getattr--
180cm
None
--getattr--

AttributeError: 无此属性

class A:
    """定制属性"""
    x = 10

    def __init__(self, name, age):
        self.name = name
        self.age = age

""" 访问属性时(无论属性是否存在)总是会调用这个方法 当同时定义__getattribute__和__getattr__时,__getattr__方法不会再被调用, 除非 __getattribute__() 显式地调用__getattr__或是引发了 AttributeError。 """ def __getattribute__(self, item): print('--getattribute--') if item == 'tall': print('180cm') else: raise AttributeError('无此属性') a = A('jack', 23) print(a.x) print(a.name) print(a.tall) # __getattr__方法无返回值所以print结果为None print(a.y)

执行结果
AttributeError: 无此属性
AttributeError: 无此属性
AttributeError: 无此属性
AttributeError: 无此属性
class A:
    """定制属性"""
    x = 10

    def __init__(self, name, age):
        self.name = name
        self.age = age

    """
    如果访问的属性存在,就不会调用__getattr__方法。这个属性的存在,包括类属性和实例属性。
    如果访问的属性不存在,才会调用此方法,可以给不存在属性设置默认值等操作
    """
    def __getattr__(self, item):
        print('--getattr--')
        if item == 'tall':
            print('180cm')
        else:
            raise AttributeError('无此属性')

    """
    访问属性时(无论属性是否存在)总是会调用这个方法
    当同时定义__getattribute__和__getattr__时,__getattr__方法不会再被调用,
    除非 __getattribute__() 显式地调用__getattr__或是引发了 AttributeError。
    """
    def __getattribute__(self, item):
        print('--getattribute--')
        # 这将调用__getattr__,如果定义了__getattr__
        # raise AttributeError('getattribute-->没有这个属性')


a = A('jack', 23)
print(a.x)
print(a.name)
print(a.tall)  # __getattr__方法无返回值所以print结果为None
print(a.y)

未开启raise AttributeError()
执行结果
AttributeError: 无此属性
AttributeError: 无此属性
AttributeError: 无此属性
AttributeError: 无此属性

开启raise AttributeError()
执行结果
--getattribute--
--getattr--

 

posted @ 2019-06-10 16:05  Noperx  阅读(854)  评论(0编辑  收藏  举报