andrew cooke a écrit : > On Apr 15, 4:06 am, Bruno Desthuilliers <bruno. > [EMAIL PROTECTED]> wrote: > >> The canonical solution is to use a custom descriptor instead of a property: (snip code) > i tried code very similar after reading the first replies and found > that it did not work as expected on setting. for example, in > > person = Person() > person.age = 27 > > "age" is set in the instance's dictionary (as 27; the descriptor is > not called), which then shadows the definition of age in the class > dictionary.
Are you sure your Person class is a new-style one (inheriting, directly or not, from object) ? The descriptor protocol doesn't work properly on old-style classes, with *exactly* the symptom you describe here (setter is not invoked, property get shadowed by an instance attribute) > my understanding was that the descriptor is only called in the class > context, The descriptor protocol is only invoked on class attributes. > so would be called if, say, a subclass tried to redefine > age. but maybe i am still confused. Possibly. > i am about to go to sleep. i guess i will try your code exactly > tomorrow, but it looks very close to mine which showed this problem. > are you sure your solution works? Yes - minus a couple (unrelated) typos ('name' instead of 'self.name' in Field.__set__, and 'self._values = []' instead of 'self._values = {}' in ActiveDAO.__init__). Here's the corrected one: class Field(object): def __init__(self, name, onchange): self.name = name self.onchange = onchange def __get__(self, instance, cls): if instance is None: # called on the class return self # called on instance return instance._values[self.name] def __set__(self, instance, value): instance._values[self.name] = self.onchange(value) class ActiveDAO(object): def __init__(self): self._values = {} class Person(ActiveDAO): name = Field('name', lambda v: v.strip().capitalize()) age = Field('age', lambda v : int(v)) -- http://mail.python.org/mailman/listinfo/python-list