获取类中属性的过程

Python的类中,属性分为实例属性和类属性。通过实例可以访问实例和类属性,通过类名只能访问类属性。下面分别就这两种方式来给出属性的访问流程。

测试代码:

class C(object):
    a = 'abc'

    def __getattribute__(self, item):
        print("__getattribute__ called.")
        return object.__getattribute__(self, item)

    def __getattr__(self, item):
        print("__getattr__ called.")
        return item + "from getattr"

    def __get__(self, instance, owner):  # 实现了__get__函数,说明C的实例是描述符
        print("__get__ called. ", end=',')
        print(instance, end=',')
        print(owner, end=',')
        print(self)
        return self

    def foo(self, x):
        print(x)

class C2(object):
    d = C()  # 描述符d只有作为类属性才有效

def main():
    e = C()
    f = C2()

    print(e.a)  # 实例访问有效属性流程:__getattribute__
    print(e.x)  # 实例访问无效属性流程:__getattribute__->__getattr__
    print(f.d.a)  # 对描述符d的访问,都要先访问__get__,流程:__get__->__getattribute__->__getattr__
    print(C.a)  # 类访问有效属性:直接访问
    print(C.x)  # 类访问无效属性:直接抛出异常
    print(C2.d.x)  # 类访问描述符访问无效属性:__get__->__getattribute__->__getattr__

if __name__ == "__main__":
    main()

对上述代码分析如下:

1、类C定义了类属性a,实例方法foo,重写了3个魔法方法 __getattribute__、__getattr__和__get__。由于C重写了__get__方法,根据Python的定义,类C属于描述符。类C2定义了类属性d,只有当描述符对象d作为类属性的时候,描述符才有效。

2、继承关系:C和C2均继承object类,属于新式类。

3、通过实例对象访问实例属性或类属性的时候,如e.a,流程如下:

      (1) 获取e的类C的mro顺序:Class C--->Class objectc,

      (2)从左至右开始查找mro列表,首先找到类C,

      (3)调用类C的魔法方法__getattribute__,此时就能找到属性a,因此不再继续进行后续查找。若此时调用该魔法方法没有找到属性,则继续调用魔法__getattr__,找到则返回,没找到则继续在mro中下一个类的重复上述过来。若mro查找完后仍然没找到,就会抛出异常

4、当类属性是一个描述符时,访问该属性时,必须在调用魔法方法__getattribute__前面调用__get__方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值