On Mon, Nov 8, 2010 at 10:13 AM, Darren Dale <[email protected]> wrote: > 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?
Yes, but it won't be a quick fix. - Robert _______________________________________________ Cython-dev mailing list [email protected] http://codespeak.net/mailman/listinfo/cython-dev
