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
>      @bar.setter
>      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...

Stefan
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to