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