Provides a secure frontend object with restricted access to attributes of the backend object.

class desc_proxy(object):
    def __init__(prx,source):
        print('proxy initialized')
        prx.source = source

    def __set__(prx, obj, value):
        print('proxy %s value of %s set to %s'%(,obj,value))
        prx.source._value[obj] = value

    def __get__(prx, obj, objtype=None):
        print('proxy %s value of %s retrieved'%(,obj))
        return prx if obj is None else prx.source._value[obj]

class desc(object):
    def __init__(this,name): # using name for printing
        print('value initialized')
        this._value = {}
        this.proxy = desc_proxy(this) = name

    def __set__(this, obj, value):
        print('%s value of %s set to %s'%(,obj,value))
        this._value[obj.proxy] = value

    def __get__(this, obj, objtype=None):
        print('%s value of %s retrieved'%(,obj))
        return this if obj is None else this._value[obj.proxy]

class base(object):
    attr = desc('attr')
    attr2 = desc('attr2')

    def __init__(this):
        this.proxy = baseProxy() # important, must be defined first!

        this.attr = 15
        this.attr2 = 10

        this.attr3 = 20 # private (not accessable via proxy)

class baseProxy(object):
    attr = base.attr.proxy
    attr2 = base.attr2.proxy

i = base()
p = i.proxy
print('\nretrieving proxy attr')
print('\nsetting proxy attr and attr2')
p.attr = 18
p.attr2 = 30
print('\nretrieving base attr')
print(i.attr) # should be 18
print('\nretrieving private attr3 from base and proxy')
#print(p.attr3) # should raise NameError

print('\ntesting multiple base instances:')
i2 = base()
p2 = i2.proxy
p2.attr = 40
print('\nretrieving base attr')
print(i.attr) # should be 18
print(i2.attr) # should be 40