__doc__ = """ __getattribute__ and __getattr__ special methods and subclasses. getattr does not override members. >>> a = getattr_boring() >>> a.boring_member 10 >>> a.resolved_by 'getattr_boring' getattribute does. >>> a = getattribute_boring() >>> a.boring_member Traceback (most recent call last): AttributeError >>> a.resolved_by 'getattribute_boring' Is inherited. >>> a = boring_boring_getattribute() >>> a.boring_getattribute_member Traceback (most recent call last): AttributeError >>> a.boring_boring_getattribute_member Traceback (most recent call last): AttributeError >>> a.resolved_by '_getattribute' __getattribute__ is always tried first, then __getattr__, regardless of where in the inheritance hiarchy they came from. >>> a = getattribute_boring_boring_getattr() >>> a.foo Traceback (most recent call last): AttributeError >>> a.resolved_by 'getattribute_boring_boring_getattr' >>> a.getattribute_boring_boring_getattr True >>> a._getattr True >>> a = getattr_boring_boring_getattribute() >>> a.foo Traceback (most recent call last): AttributeError >>> a.resolved_by '_getattribute' >>> a.getattr_boring_boring_getattribute True >>> a._getattribute True """ cdef class boring: cdef readonly int boring_member def __init__(self): self.boring_member = 10 cdef class getattr_boring(boring): def __getattr__(self,n): if n == 'resolved_by': return 'getattr_boring' elif n == 'getattr_boring': return True else: raise AttributeError cdef class getattribute_boring(boring): def __getattribute__(self,n): if n == 'resolved_by': return 'getattribute_boring' elif n == 'getattribute_boring': return True else: raise AttributeError cdef class _getattr: def __getattr__(self,n): if n == 'resolved_by': return '_getattr' elif n == '_getattr': return True else: raise AttributeError cdef class _getattribute(boring): def __getattribute__(self,n): if n == 'resolved_by': return '_getattribute' elif n == '_getattribute': return True else: raise AttributeError cdef class boring_getattribute(_getattribute): cdef readonly int boring_getattribute_member cdef class boring_boring_getattribute(boring_getattribute): cdef readonly int boring_boring_getattribute_member cdef class boring_getattr(_getattr): cdef readonly int boring_getattr_member cdef class boring_boring_getattr(boring_getattr): cdef readonly int boring_boring_getattr_member cdef class getattribute_boring_boring_getattr(boring_boring_getattr): def __getattribute__(self,n): if n == 'resolved_by': return 'getattribute_boring_boring_getattr' elif n == 'getattribute_boring_boring_getattr': return True else: raise AttributeError cdef class getattr_boring_boring_getattribute(boring_boring_getattribute): def __getattr__(self,n): if n == 'resolved_by': return 'getattr_boring_boring_getattribute' elif n == 'getattr_boring_boring_getattribute': return True else: raise AttributeError