2011/8/26 Lauro Moura <lauro.n...@openbossa.org>:
> On Fri, Aug 26, 2011 at 2:30 PM, Sebastian Wiesner
> <lunary...@googlemail.com> wrote:
>> 2011/8/26 Lauro Moura <lauro.n...@openbossa.org>:
>>> On Fri, Aug 26, 2011 at 1:53 PM, Markus Hubig <mhu...@imko.de> wrote:
>>>> Hi @all,
>>>> in psep-0104 the use of the use of the decorator style @Property's is
>>>> documented like this:
>>>> class C(QObject):
>>>>
>>>>     def __init__(self):
>>>>         self._x = None
>>>>
>>>>     xChanged = Signal()
>>>>
>>>>     @Property(float, doc="I'm the 'x' property.", notify=xChanged)
>>>>     def x(self):
>>>>         return self._x
>>>>
>>>>     @x.setter
>>>>     def x(self, value):
>>>>         self._x = value
>>>>
>>>> But in my tests I can't give the setter and getter the same name (x).
>>>> So in this example I had to name the setter eg. _x(self, value) to got
>>>> it Working ... got me a while to figure this out! Seems like a bug!?
>>>>
>>>
>>> @mydecorator
>>> def method(self):
>>>   pass
>>>
>>> is equivalent to
>>>
>>> def method(self):
>>>   pass
>>> method = mydecorator(method)
>>
>> These snippets are not completely equivalent.  While they somehow have
>> similar semantics, there a subtle differences when it comes to name
>> binding.
>>
>> The second example actually binds "method" in the module namespace,
>> *before* the decorator is executed, but the first example does *not*.
>> In a definition with decorator syntax, the function is not created in
>> the module namespace, but in an entirely new namespace.  The decorator
>> is evaluated in this new namespace, and only the *return value* of the
>> decorator is eventually bound in the module namespace.  See language
>> reference [1] for further details.
>>
>
> Yep, looking at an disassemble of a simple example there's this
> (subtle) difference. When the decorator is used only the result is
> assigned to the "method" name in the current namespace while the
> non-decorator version stores "method" twice. One for the original
> version and another for the decorated version.
>
> What do you mean by "the function is not created in the module
> namespace"? The docs states: "Decorator expressions are evaluated when
> the function is defined, in the scope that contains the function
> definition. ".

I stand corrected.  Basically I just wanted to say that decorated
functions are never bound to module namespace by themselves, but the
quoted statement is of course not correct.  Decorated functions are
evaluated in the module namespace, they are just not immediately bound
to it.

>> Thus, your assumption
>>
>>> So, your code is reassigning the 'x' name, overwriting the first one.
>>
>> is wrong.   The name is not reassigned, because the second "def x(…)"
>> never binds to module namespace. Only the return value of "x.setter"
>> (which is the property decorator again) is bound in the module
>> namespace.
>>
>
> "...the return value of 'x.setter' is bound in the module
> namespace"... to the name "x", which means it is indeed overwritten in
> the class namespace.

I was just referring to the function definition "def x(…)".  I thought
that "x.setter" returned the Property object again, so that "x" was
bound to the same object again, and not really overwritten.

> It would work as Markus asked only if x.setter() return the Property
> object itself ... which does not, and I don't think it should.

I stand corrected again.  I didn't know that "x.setter()" returns the
decorated function, but not the Property object.  I blindly assumed
the latter, because the built-in property as well as
"PyQt.QtCore.pyqtProperty" behave this way.

Not returning the property object, but the function, is very
surprising to any Python programmer, to say the least.
"Property.setter" should really return the "Property" object again to
be consistent with "pyqtProperty" and the built-in "property" and so
to match the expectations of Python and PyQt programmers.

> It would break, for example, Qt properties where they take the form of
> "x" for getters and "setX" for setters. If the name "setX" is replaced
> by the Property object, calling myobj.setX(arg) would call
> Property.__call__(arg), which is already used to assign the getter
> function.

I think, that this case can (and should) be ignored.  Separate getter
and setter, with the setter still being available in the namespace
after the property declaration, is a C++ idiom.  In Python the idiom
given by the built-in "property" is different: getter and setter  are
hidden and only the property remains available in the class namespace.
 As "Property" is used to declare properties on the Python side, it
should support Python idioms, not C++ ones.

The above case is broken anyway, because with "x" being bound to a
"Property" object, there is no getter counterpart to the setter
"setX()" anymore.  With "setX()" being available, one might try to
call "x()" and be surprised to see this fail.

And after all, in the above case, you can still declare the property
without decorators by explicitly creating the "Property" object, so
the breakage can easily be avoided.

Sebastian Wiesner
_______________________________________________
PySide mailing list
PySide@lists.pyside.org
http://lists.pyside.org/listinfo/pyside

Reply via email to