[Python-Dev] Defining properties - a use case for class decorators?

Josiah Carlson jcarlson at uci.edu
Tue Oct 18 19:23:59 CEST 2005


Nick Coghlan <ncoghlan at gmail.com> wrote:
> 
> Jim Jewett wrote:
> > That said, I'm not sure the benefit is enough to justify the
> > extra complications, and your suggestion of allowing strings
> > for method names may be close enough.  I agree that the
> > use of strings is awkward, but ... probably no worse than
> > using them with __dict__ today.
> 
> An idea that was kicked around on c.l.p a long while back was "statement local 
> variables", where you could define some extra names just for a single simple 
> statement:
> 
>    x = property(get, set, delete, doc) given:
>        doc = "Property x (must be less than 5)"
>        def get(self):
>            try:
>                return self._x
>            except AttributeError:
>                self._x = 0
>                return 0
>        def set(self, value):
>            if value >= 5: raise ValueError("value too big")
>            self._x = x
>        def delete(self):
>            del self._x
> 
> As I recall, the idea died due to problems with figuring out how to allow the 
> simple statement to both see the names from the nested block and modify the 
> surrounding namespace, but prevent the names from the nested block from 
> affecting the surrounding namespace after the statement was completed.

You wouldn't be able to write to the surrounding namespace, but a
closure would work fine for this.

    def Property(fcn):
        ns = fcn()
        return property(ns.get('get'), ns.get('set'), ns.get('delete'), ns.get('doc'))

    class foo(object):
        @Property
        def x():
            doc = "Property x (must be less than 5)"
            def get(self):
                try:
                    return self._x
                except AttributeError:
                    self._x = 0
                    return 0
            def set(self, value):
                if value >= 5: raise ValueError("value too big")
                self._x = value
            def delete(self):
                del self._x
            return locals()

In an actual 'given:' statement, one could create a local function
namespace with the proper func_closure attribute (which is automatically
executed), then execute the lookup of the arguments to the statement in
the 'given:' line from this closure, but assign to surrounding scope.
Then again, maybe the above function and decorator approach are better.


An unfortunate side-effect of with statement early-binding of 'as VAR'
is that unless one works quite hard at mucking about with frames, the
following has a wholly ugly implementation (whether or not one cares
about the persistance of the variables defined within the block, you
still need to modify x when you are done, which may as well cause a
cleanup of the objects defined within the block...if such things are
possible)...

with Property as x:
    ...


> Another option would be to allow attribute reference targets when binding 
> function names:

*shivers at the proposal*  That's scary.  It took me a few minutes just
to figure out what the heck that was supposed to do.

 - Josiah



More information about the Python-Dev mailing list