当获取元素的时候,实际上调用的是object.__getattribute__(key)
所谓的搜索优先级实际上是object.__getattribute__(key)实现的
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))