On Mon, Nov 8, 2010 at 11:01 AM, Stefan Behnel <[email protected]> wrote: > Darren Dale, 08.11.2010 16:24: >> On Mon, Nov 8, 2010 at 10:05 AM, Stefan Behnel wrote: >>> Darren Dale, 08.11.2010 15:34: >>>> Python-2.6 extended the definition of property to include getter, >>>> setter, and deleter methods that can be used as decorators. This >>>> allows a really nice pattern for declaring properties without >>>> populating the namespace with a bunch of private methods: >>>> >>>> class Foo(object): >>>> >>>> _bar = None >>>> @property >>>> def bar(self): >>>> return self._bar >>>> @bar.setter >>>> def bar(self, val): >>>> self._bar = val >>>> >>>> What happens is @bar.setter makes a copy of bar, updates the copy to >>>> use the decorated method as the setter, and returns the copy, which is >>>> then bound to the name of the decorated function. The decorated >>>> function has to be called bar, so that the updated copy is bound to >>>> bar, replacing the original. >>>> >>>> Attempting to cythonize this example yields an error: >>>> >>>> $ python setup.py build_ext --inplace >>>> running build_ext >>>> cythoning test_property.pyx to test_property.c >>>> >>>> Error converting Pyrex file to C: >>>> ------------------------------------------------------------ >>>> ... >>>> _bar = None >>>> @property >>>> def bar(self): >>>> return self._bar >>>> @bar.setter >>>> def bar(self, val): >>>> ^ >>>> ------------------------------------------------------------ >>>> >>>> /Users/darren/temp/test/test_property.pyx:11:4: 'bar' already declared >>>> >>>> Would it be possible for Cython to support this pattern? >>> >>> The problem is not the property behaviour, it's the mapping from a Python >>> function/method to a C function, which must have a unique name. Currently, >>> functions are unique within one namespace, be it the module namespace or a >>> class body namespace. They are actually looked up statically, not >>> dynamically in definition order, so the fix is not as easy as adding a >>> counted ID to the C-level name. >>> >>> The above might actually work if you change one of the method names, i.e. >>> either the getter or setter name. If it works as you say, the setter name >>> shouldn't have any impact on the result. >> >> Sorry, I should have emphasized the point about the importance of the >> setter name. It *must* be the same as the original property. >> >> class Foo(object): >> >> _bar = None >> �...@property >> def bar(self): >> return self._bar >> �[email protected] >> def bar_(self, val): >> self._bar = val >> >> That produces a class with two properties: bar and bar_. Foo.bar is a >> property with a getter but no setter. Foo.bar_ is a property with a >> getter and a setter. > > Renaming the getter works for me, though: > > class Foo(object): > _bar = None > > @property > def bar_(self): > return self._bar > > @bar_.setter > def bar(self, val): > self._bar = val > > del bar_ > > f = Foo() > print f.bar > f.bar = 5 > print f.bar > > try: > Foo.bar_ > except AttributeError: > pass > except: > print "hoppsa!" > > I admit that it's ugly to do a "del bar_" at the end, but it's not more > than a work-around after all...
Oh, that's what you meant. I suppose that is a reasonable workaround. Is issue 489 solvable? _______________________________________________ Cython-dev mailing list [email protected] http://codespeak.net/mailman/listinfo/cython-dev
