On Thu, Mar 17, 2016 at 5:29 PM, Steven D'Aprano
<[email protected]> wrote:
> I don't think that property is a similar situation. I think what happens
> here is that the first call to property sets:
>
> # @property def x...
> x = property(x)
>
> Then the second decorator does:
>
> # @x.setter def x...
> x = x.setter(x)
>
> which replaces x with a brand new property object.
Okay. Let's try this.
>>> class Demo:
... @property
... def x(self):
... print("Getting x")
... return 42
... @x.setter
... def x(self, value):
... print("Setting x to", value)
...
>>> d = Demo()
>>> d.x
Getting x
42
>>> d.x = 1
Setting x to 1
Decorators work. Now let's try NOT using decorators.
>>> class Demo:
... def x(self):
... print("Getting x")
... return 42
... x = property(x)
... def x(self, value):
... print("Setting x to", value)
... x = x.setter(x)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in Demo
AttributeError: 'function' object has no attribute 'setter'
Since the 'def' line bound the undecorated function to the name 'x',
the decoration underneath *fails*. The only way this could work would
be with a temporary name for either the new function or the decorator:
>>> class Demo:
... def x(self):
... print("Getting x")
... return 42
... x = property(x)
... decorator = x.setter
... def x(self, value):
... print("Setting x to", value)
... x = decorator(x)
... del decorator
...
>>> d = Demo()
>>> d.x
Getting x
42
>>> d.x = 1
Setting x to 1
This is how CPython implements this (it evaluates the decoration
expressions first, leaving them on the stack, then creates the
function, then calls the decorators), but I don't see anywhere that
this is guaranteed in the docs either - the only way I know this is
current behaviour is from trying it (with dis.dis). The documented
equivalence simply doesn't work.
Note, by the way, that I am not in any way criticising the *behaviour*
here. I don't think anything needs to be changed as regards
functionality. And it's not even that big an issue as regards
documentation. It's mainly just an esoteric curiosity.
ChrisA
--
https://mail.python.org/mailman/listinfo/python-list