From: eb303 on 27 May 2010 08:37 Hello all, I've been using Python properties quite a lot lately and I've found a few things that are a bit annoying about them in some cases. I wondered if I missed something or if anybody else has this kind of problems too, and if there are better solutions than the ones I'm using ATM. The first annoyance is when I want to specialize a property in a subclass. This happens quite often actually, and it is even sometimes the reason why a plain attribute is turned into a property: a subclass needs to do more things than the superclass when the property is updated for example. So, of course, my first try was: class A(object): def __init__(self): self._p = None def _get_p(self): return self._p def _set_p(self, p): self._p = p p = property(_get_p, _set_p) class B(A): def _set_p(self, p): ## Additional things here super(B, self)._set_p(p) And of course, it doesn't work: the property has been bound to A._set_p in A, so any new definition of _set_p in any subclass does not replace the set method for the property. So I always have to add a line: p = property(A._get_p, _set_p) in the subclass too. This is a bit awkward to me, since I have to specify the superclass's name (super( ) can't be used, since it should take B as an argument, and B isn't defined yet ). Do I miss something? Is this the way to do it, or is there a better one? The second annoyance is when I have a property that is a list of something. I often have to do something when the contents of the list is modified. So basically, I often end up doing the following: def C(object): def __init__(self): self._l = [] def _get_l(self): return list(self._l) def _set_l(self, l): self._l = list(l) l = property(_get_l, _set_l) But then, I have to do: o = C() l = o.l l.append(42) o.l = l instead of just doing: o.l.append(42) which would seem much more natural IMHO. Is there any not too complicated way to have o.l.append( ) call something in C? And the same for o.l.remove( ), o.l[i] = , and everything else updating the list contents? Thanks! - Eric -
From: Neil Cerutti on 27 May 2010 09:14 On 2010-05-27, eb303 <eric.brunel.pragmadev(a)gmail.com> wrote: > I've been using Python properties quite a lot lately and I've > found a few things that are a bit annoying about them in some > cases. I wondered if I missed something or if anybody else has > this kind of problems too, and if there are better solutions > than the ones I'm using ATM. > The first annoyance is when I want to specialize a property in a > subclass. See: URI:http://infinitesque.net/articles/2005/enhancing%20Python%27s%20property.xhtml -- Neil Cerutti *** You found a dead moose-rat. You sell the hide for $200. ***
From: Christian Heimes on 27 May 2010 09:24 > Do I miss something? > Is this the way to do it, or is there a better one? A better way was introduced in Python 2.6. See http://docs.python.org/library/functions.html?highlight=property#property I have a Python only version around if you are still using Python 2.5. Christian
From: John Posner on 27 May 2010 13:10 On 5/27/2010 9:14 AM, Neil Cerutti wrote: > On 2010-05-27, eb303<eric.brunel.pragmadev(a)gmail.com> wrote: >> I've been using Python properties quite a lot lately and I've >> found a few things that are a bit annoying about them in some >> cases. I wondered if I missed something or if anybody else has >> this kind of problems too, and if there are better solutions >> than the ones I'm using ATM. > >> The first annoyance is when I want to specialize a property in a >> subclass. > > See: > > URI:http://infinitesque.net/articles/2005/enhancing%20Python%27s%20property.xhtml > Very nice idea, but I think this solution works too hard and not quite correctly. In Python 2.6.5, checking the name of the OProperty object's "fget" method: if self.fget.__name__ == '<lambda>' or not self.fget.__name__: .... doesn't distinguish between the original class's get-the-value method and the derived class's. (Did something change between 2005-11-02 and now?) Moreover, you don't *need* to perform this check -- just let *getattr* do the work of finding the right method. These method defs work fine for me: def __get__(self, obj, objtype): if self.fget: return getattr(obj, self.fget.__name__)() else: raise AttributeError, "unreadable attribute" def __set__(self, obj, value): if self.fset: getattr(obj, self.fset.__name__)(value) else: raise AttributeError, "can't set attribute" -John
From: Francesco Bochicchio on 27 May 2010 14:56
On 27 Mag, 14:37, eb303 <eric.brunel.pragma...(a)gmail.com> wrote: > Hello all, > > I've been using Python properties quite a lot lately and I've found a > few things that are a bit annoying about them in some cases. I > wondered if I missed something or if anybody else has this kind of > problems too, and if there are better solutions than the ones I'm > using ATM. > > The first annoyance is when I want to specialize a property in a > subclass. This happens quite often actually, and it is even sometimes > the reason why a plain attribute is turned into a property: a subclass > needs to do more things than the superclass when the property is > updated for example. So, of course, my first try was: > > class A(object): > def __init__(self): > self._p = None > def _get_p(self): > return self._p > def _set_p(self, p): > self._p = p > p = property(_get_p, _set_p) > class B(A): > def _set_p(self, p): > ## Additional things here > super(B, self)._set_p(p) > > And of course, it doesn't work: the property has been bound to > A._set_p in A, so any new definition of _set_p in any subclass does > not replace the set method for the property. So I always have to add a > line: > p = property(A._get_p, _set_p) > in the subclass too. This is a bit awkward to me, since I have to > specify the superclass's name (super( ) can't be used, since it should > take B as an argument, and B isn't defined yet ). Do I miss something? > Is this the way to do it, or is there a better one? > Don't know if is better, but you could add a level of indirection to solve it class A(object): def __init__(self): self._p = None def _get_p(self): return self._p def _set_p(self, p): self._p = p def _virtual_get_p (self): _get_p(self) def _virtual_set_p (self,v): _set_p(self, v) p = property(_virtual_get_p, _virtual_set_p) At this point, the subclasses of A can reimplement _get_p and _set_p as they like (I think) Ciao ----- FB |