python屬性訪問優先級

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

相關文章
相關標籤/搜索