@x.setter property implementation

Arnaud Delobelle arnodel at googlemail.com
Thu Apr 10 12:09:36 EDT 2008


On Apr 10, 3:37 pm, Floris Bruynooghe <floris.bruynoo... at gmail.com>
wrote:
> On Apr 7, 2:19 pm, "Andrii V. Mishkovskyi" <misho... at gmail.com> wrote:
>
> > 2008/4/7, Floris Bruynooghe <floris.bruynoo... at gmail.com>:
>
> > >  Have been grepping all over the place and failed to find it.  I found
> > >  the test module for them, but that doesn't get me very far...
>
> > I think you should take a look at 'descrobject.c' file in 'Objects' directory.
>
> Thanks, I found it!  So after some looking around here was my
> implementation:
>
> class myproperty(property):
>     def setter(self, func):
>         self.fset = func
>
> But that doesn't work since fset is a read only attribute (and all of
> this is implemented in C).
>
> So I've settled with the (nearly) original proposal from Guido on
> python-dev:
>
> def propset(prop):
>     assert isinstance(prop, property)
>     @functools.wraps
>     def helper(func):
>         return property(prop.fget, func, prop.fdel, prop.__doc__)
>     return helper
>
> The downside of this is that upgrade from 2.5 to 2.6 will require code
> changes, I was trying to minimise those to just removing an import
> statement.
>
> Regards
> Floris

Here's an implementation of prop.setter in pure python < 2.6, but
using sys._getframe, and the only test performed is the one below :)

import sys

def find_key(mapping, searchval):
    for key, val in mapping.iteritems():
        if val == searchval:
            return key

_property = property

class property(property):
    def setter(self, fset):
        cls_ns = sys._getframe(1).f_locals
        propname = find_key(cls_ns, self)
        # if not propname: there's a problem!
        cls_ns[propname] = property(self.fget, fset,
                                    self.fdel, self.__doc__)
        return fset
    # getter and deleter can be defined the same way!

# -------- Example -------

class Foo(object):
    @property
    def bar(self):
        return self._bar
    @bar.setter
    def setbar(self, x):
        self._bar = '<%s>' % x

# -------- Interactive test -----
>>> foo = Foo()
>>> foo.bar = 3
>>> foo.bar
'<3>'
>>> foo.bar = 'oeufs'
>>> foo.bar
'<oeufs>'
>>>

Having fun'ly yours,

--
Arnaud




More information about the Python-list mailing list