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
