1 属性访问优先级为html
1 __getattribute__(), 入口ui
2 数据描述符spa
3 实例对象的字典 obj.__dict__ (若与描述符同对象名,会被覆盖) .net
4 类的字典 Class.__dict__ code
5 非数据描述符htm
6 父类的字典对象
7 __getattr__() blog
2 调用流程继承
假设咱们有个 类A ,其中 a是A的实例
当调用 a.x 时候属性访问顺序以下:ip
0 __getattribuite__ 为入口
1 若是重载了 __getattribute__ ,则调用.
2 若是遇到 数据型 descriptor 会覆盖 a.__dict__ 优先调用 a.__class__.__dict__ 的 数据型 descriptor
3 a.__dict__ , 实例中是不容许有 descriptor 的,因此不会遇到descriptor
4 A.__dict__ , 也即 a.__class__.__dict__ .
5 若是遇到了 非数据型descriptor ,则会在搜索父类属性前优先调用
6 沿着继承链搜索父类.搜索 a.__class__.__bases__ 中的全部 __dict__ . 若是有多重继承且是菱形继承的状况,按 MRO(Method Resolution Order) 顺序搜索.
7 若是以上都搜不到, 就会触发 a.__getattr__, 则抛 AttributeError 异常.
3 实际示例
class Des(object): def __init__(self, name): # 第二步,描述符对象初始化 self.name = name print("__init__(): name = ", self.name) # 第十步 调用描述符Des的__get__方法 def __get__(self, instance, owner): print("__get__() ...") return self.name # 第六步 实例f._x = x时调用完__setter__后调用__set__ def __set__(self, instance, value): print 'im set' print value print 'set over' class Foo(object): # 第一步 建立描述符对象 # 第九步 由于 Foo._x 为数据型描述符,因此覆盖掉对象f._x _x = Des('wwt') temp = 'im temp' # 第四步 初始化实例f def __init__(self, x): self._x = x # 第八步 先会访问更改后的__getattribute__方法 def __getattribute__(self, item): print 'im getattribute' return super(Foo, self).__getattribute__(item) # 第五步 实例f._x = x时调用__setattr__ def __setattr__(self, key, value): print 'im setter' return super(Foo, self).__setattr__(key, value) # 第三步 建立Foo对象f f = Foo(10) # 第七步 对象f属性获取 print f._x # 由于对象f._x被Foo._x的描述符覆盖,因此返回为 wwt
''' out: ('__init__(): name = ', 'wwt') im setter im set 10 set over im getattribute __get__() ... wwt '''
本文参考
Jimmy_Nie 的文章,地址为 http://www.cnblogs.com/Jimmy1988/p/6808237.html
luozhaoyu 的文章, 地址 http://www.jb51.net/article/86749.htm