Item 23: getattribute

class A(object):
    def __init__(self):
        self.x = 5

    def __getattr__(self, name):
        print('    A.__getattr__', self, name)
        if name and name[0].isalpha():
            setattr(self, name, 10)
            return 10
        raise AttributeError('cannot get ' + name)

class B(A):
    def __getattribute__(self, name):
        print('    B.__getattribute__', self, name)
        if name == 'z':
            return 15
        raise AttributeError('cannot get ' + name)

a = A()
print('P1:', a.x, a.x)
print('P2:', a.y, a.y)
b = B()
print('P3:', b.x, b.x)
print('P4:', b.y, b.y)
print('P5:', b.z, b.z)