python __getattribute__ 的优先级问题

本文深入探讨Python中描述符的工作原理,特别是数据描述符与非数据描述符的区别,以及它们如何影响属性的查找顺序。通过具体例子说明不同情况下属性的获取流程。

The way __getattribute__() works needs to be covered, as it was implemented to behave in a very specific way. Thus it is very important to recognize this ordering:

  • Class attributes

  • Data descriptors

  • Instance attributes

  • Non-data descriptors

  • Defaulting to __getattr__()

A descriptor is a class attribute, so all class attributes have the highest priority.……这个是在core python programming 13.16节摘录下来的,这个是让我很困惑的地方;原因在于Class attributes 与Instance attributes的优先级问题;看下面的例子:

class Test(object): a = 15 <pre name="code" class="python">>>> t = Test() >>> t.a 15 >>> t.a = 20 >>> t.a 20<pre name="code" class="python">>>> del t.a >>> t.a 15</pre></pre>



针对没有描述符的情况下,这个查找顺序应该是先查找的t.__dict__,然后才查找的Test.__dict__,总结起来就是先在obj.__dict__中查找,然后再查找obj.__class__.__dict__;

 

 

有数据描述符的情况下:

class DevNull(object): def __get__(self, obj, typ=None): print 'Accessing attribute... ignoring' def __set__(self, obj, val): print 'Attempt to assign %r... ignoring' % (val) >>> class Test1(object): a = DevNull() >>> t1 = Test1() >>> t1.a Accessing attribute... ignoring >>> t1.a = 123 Attempt to assign 123 ... ignoring >>> t1.__dict__['a'] = 123 >>> t1.a Accessing attribute... ignoring >>> t1.__dict__['a'] 123 结果一幕了然,由于a是一个类属性,同时是一个数据描述符,__getattribute__在查找时应该是先访问了Test1.__dict__,如果存在且是数据描述符,则调用描述符的__get__or__set__,翻译起来就是:先查找type(obj).__dict__,如果属性存在并且是数据描述符,则执行data descriptor的__get__or__set__;

结论:属性/方法查找顺序

 

1.如果attr是一个Python自动产生的属性,找到!(优先级非常高!)

2.查找obj.__class__.__dict__,如果attr存在并且是data descriptor,返回data descriptor的__get__方法的结果,如果没有继续在obj.__class__的父类以及祖先类中寻找data descriptor

3.在obj.__dict__中查找,这一步分两种情况,第一种情况是obj是一个普通实例,找到就直接返回,找不到进行下一步。第二种情况是obj是一个类,依次在obj和它的父类、祖先类的__dict__中查找,如果找到一个descriptor就返回descriptor的__get__方法的结果,否则直接返回attr。如果没有找到,进行下一步。

4.在obj.__class__.__dict__中查找,如果找到了一个descriptor(插一句:这里的descriptor一定是non-data descriptor,如果它是data descriptor,第二步就找到它了)descriptor的__get__方法的结果。如果找到一个普通属性,直接返回属性值。如果没找到,进行下一步。

5.Defaulting to __getattr__()

6.raise AttributeError

 

 

引用:

http://onlypython.group.iteye.com/group/wiki/1362-python-39-s-descriptor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值