python属性の検索優先度

3402 ワード

要素を取得すると、実際に呼び出されるのはobject._です.getattribute__(key)検索優先度とは実際にobject._getattribute__実装された
Data DescriptorとNon-data Descriptorの違いは、インスタンス辞書エントリの上書きと計算順序に反映されます.インスタンス辞書にData Descriptorと同じ名前のプロパティが含まれている場合は、Data Descriptorが優先されます.インスタンス辞書にNon-data Descriptorと同じ名前のプロパティが含まれている場合は、インスタンス辞書が優先されます.同時定義_get__()と_set__()メソッド、そして_set__()呼び出し時にAttributeError例外を投げ出すと、読み取り専用のData Descriptorを作成できます.例外を放出する_を定義するだけです.set__()メソッドは,そのオブジェクトをData Descriptorにするのに十分である.
メソッドは実際には非データ記述子です.
次はobject._getattribute__(key)の偽コードといくつかのインスタンスは、勝手に遊んでいます.
class demo(object):#       
    def __init__(self, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs

    def __get__(self, instance, owner):
        return owner.__dict__[type(self).__name__](instance, *self.args, **self.kwargs)

class Descriptor(object):
    def __get__(self, instance, owner):
        return 'Descriptor'
    def __set__(self, instance, value):
        pass
class FOO(object):
    def __getattr__(self, item):
        return '__getattr__'
    def __init__(self, *args, **kwargs):
        pass
    # attr = Descriptor()
    demo = demo()
    # def demo(self):
    #    pass
    def __del__(self):
        pass
foo = FOO(1, 2, 3)

# foo.attr = 'instance attr'
# FOO.attr = 'class attr'
# type(foo).__dict__['attr'].__get__(foo, type(foo))
# FOO.__dict__['attr'].__get__(None, FOO)
print foo.attr
print FOO.attr

print FOO.__dict__['demo'] # 
print FOO.demo # 
print foo.demo # >

print FOO.__dict__['demo'].__get__(None, FOO) == FOO.demo #True
print type(foo).__dict__['demo'].__get__(foo, type(foo)) == foo.demo # #True



object.__getattribute__(key)のダミーコード
def __getattribute__(self, key):
    # self    
    if type(type) == type(self):
        pass
        #      ,  1,    __getattr__2,                 。(unbound method)
    # self     
    else:
        #       
        _attr = type(self).__dict__.get(key)
        if _attr and hasattr(_attr, '__get__') and hasattr(_attr, '__set__'):
            _value = type(self).__dict__[key]
            if hasattr(_value, '__get__'):
                return _value.__get__(self, type(self))
            return _value
        del _attr
        #     
        _attr = self.__dict__.get(key)
        if _attr:
            return _attr
        del _attr
        #       
        _attr = type(self).__dict__.get(key)
        if _attr and hasattr(_attr, '__get__'):
            _value = type(self).__dict__[key]
            if hasattr(_value, '__get__'):
                return _value.__get__(self, type(self))
            return _value
        del _attr
        #    
        _attr = type(self).__dict__.get(key)
        if _attr:
            return _attr
        #     
        for FClass in self.__class__.__mro__:
            _attr = FClass.__dict__.get(key)
            if _attr:
                return _attr
        # __getattr__
        if hasattr(self, '__getattr__'):
            return self.__getattr__(key)
        else:
            raise AttributeError('type object "{1}" has no attribute "{2}"'.format(str(self.__class__), key))