class C1(object):
def __init__(self):
self._p1 = 1
def p1_get(self):
return self._p1
def p1_set(self, v):
self._p1 = v
p1 = property(p1_get, p1_set)
class C2(C1):
def p1_get(self):
return self._p1 * 100
c1 = C1()
assert c1.p1 == 1
c2 = C2()
assert c1.p1 == 100 ### ERROR
class NiceProperty(object):
def __init__(self, defvalue=None):
self.defvalue = defvalue
def set_name(self, name):
self.name = name
self.getter_name = name + '_get'
self.setter_name = name + '_set'
self.private_name = '_' + name
def __get__(self, inst, owner):
f = getattr(inst, self.getter_name)
return f()
def __set__(self, inst, value):
f = getattr(inst, self.setter_name)
f(value)
def create_getter(self):
vars = dict()
exec 'def f(x):return x.{}'.format(self.private_name) in vars
return vars['f']
def create_setter(self):
vars = dict()
exec 'def f(x, y):x.{} = y'.format(self.private_name) in vars
return vars['f']
class MetaclassNiceProperty(type):
def __new__(cls, name, bases, dict_):
d1_ = dict(dict_) # copy dict_
for k, v in d1_.iteritems():
if isinstance(v, NiceProperty):
v.set_name(k)
if v.getter_name not in d1_:
dict_[v.getter_name] = v.create_getter()
if v.setter_name not in d1_:
dict_[v.setter_name] = v.create_setter()
# create private-attribute for property with default value
dict_[v.private_name] = v.defvalue
return type.__new__(cls, name, bases, dict_)
if __name__ == '__main__':
class Base(object):
__metaclass__ = MetaclassNiceProperty
class WithProp(Base):
prop1 = NiceProperty('s1')
prop2 = NiceProperty(1)
class WithProp2(WithProp):
def prop2_get(self):
return self._prop2 * 100
a1 = WithProp2()
assert a1.prop1 == 's1'
assert a1.prop2 == 100
a1.prop2 = 2
assert a1.prop2 == 200
В итоге - просто объявляем свойство и получаем getter/setter/private-attribute. И в потомках методы нормально отрабатываются.
Что скажете?