Aug
10
2008
Attribute Access Machinery of New Style Objects/Classes
Attribute access of form obj.d triggers the special method type(obj).__getattribute__ to be invoked.
Thus, for objects, it is object.__getattribute__ that defines the general machinery of attribute access. The implementation in python code is as follows:
def __getattribute__(obj, name):
cls = type(obj)
class_attr = class_lookup(cls, name)
# data descriptor
if class_attr and is_data_desc(class_attr):
return class_attr.__get__(obj, cls)
# object attribute
if name in obj.__dict__:
return obj.__dict__[name]
if class_attr:
# non-data descriptor
if is_desc(class_attr)
return class_attr.__get__(obj, cls)
# ordinary class attribute
else:
return class_attr
raise AttributeError(name)
For classes, it is type.__getattribute__ that defines the general machinery of attribute access. The implementation in python code is as follows:
def __getattribute__(cls, name):
meta_cls = type(cls)
meta_attr = class_lookup(meta_cls, name)
# data descriptor in metaclass
if meta_attr and is_data_desc(meta_attr):
return meta_attr.__get__(cls, meta_cls)
class_attr = class_lookup(cls, name)
if class_attr:
# descriptor
if is_desc(class_attr):
return class_attr.__get__(None, cls)
# ordinary class attribute
else:
return class_attr
if meta_attr:
# non-data descriptor in metaclass
if is_desc(meta_attr):
return meta_attr.__get__(cls, meta_cls)
# ordinary meta attribute
else:
return meta_attr
raise AttributeError(name)
As the cooperative base class attribute access mechanism, super has a custom __getattribute__ method. The implementation in python code is as follows:
def __getattribute__(self, name):
# unbound super object, or class of super object is queried
if self.__self__ is None or name == '__class__':
return object.__getattribute__(self, name)
starttype = self.__self_class__
mro = iter(starttype.__mro__)
for cls in mro:
if cls is self.__thistype__:
break
# Note: mro is an iterator, so the second loop
# picks up where the first one left off!
for cls in mro:
if name in cls.__dict__:
x = cls.__dict__[name]
if is_desc(x):
# only pass 'obj' param if this is instance-mode super
return x.__get__(None if self.__self__ is starttype else self.__self__, starttype)
else:
return x
# fall back on the generic attribute access
return object.__getattribute__(self, name)
Loading...