Item 21: Descriptors

class Field(object):
    def __init__(self, name):
        self.name = '__' + name
    def __get__(self, instance, owner):
        print('__get__', self, instance, owner)
        return getattr(instance, self.name)
    def __set__(self, instance, value):
        print('__set__', self, instance, value)
        setattr(instance, self.name, value)

class Record(object):
    a = Field('a')
    b = Field('b')
    def __init__(self, a, b):
        self.a = a
        self.b = b

s = Record(1, 2)
t = Record(3, 4)
print(s.a, s.b, t.a, t.b)
print(s.a, s.b, t.a, t.b)

try:
    print(Record.a)
except AttributeError as e:
    print('Caught:', repr(e))