Decorator
Chris Angelico
rosuav at gmail.com
Thu Feb 9 02:19:07 EST 2017
On Thu, Feb 9, 2017 at 6:03 PM, ast <nomail at com.invalid> wrote:
> class Temperature:
> def __init__(self):
> self.value = 0
>
> # @property
> def celsius(self): return self.value
> celsius = property(celsius)
> # @celsius.setter def celsius(self, value): <--
> overwrites previous celsius
> self.value = value
>
> celsius = celsius.setter(celsius) <-- error here
>
The difference is that the decorator line is evaluated before the
function is defined. Try this:
class Temperature:
def __init__(self):
self.value = 0
#@property
def celsius(self):
return self.value
celsius = property(celsius)
#@celsius.setter
_tmp = celsius.setter
def celsius(self, value):
self.value = value
celsius = _tmp(celsius)
del _tmp
Now it'll work.
(Actually, there are some other very minor subtleties; the name isn't
temporarily bound to the undecorated function prior to the decorator
being called. But in this case, it's simply an order of evaluation.)
In CPython (3.7 on Debian Linux, fwiw), the decorated function is
processed like this:
@celsius.setter
#_tmp = celsius.setter
def celsius(self, value):
self.value = value
#celsius = _tmp(celsius)
#del _tmp
11 28 LOAD_NAME 5 (celsius)
30 LOAD_ATTR 6 (setter)
32 LOAD_CONST 5 (<code object celsius at
0x7f8ba4b735d0, file "123123123.py", line 11>)
34 LOAD_CONST 4
('Temperature.<locals>.Temperature.celsius')
36 MAKE_FUNCTION 0
38 CALL_FUNCTION 1
40 STORE_NAME 5 (celsius)
In other words:
1) Evaluate "celsius.setter" and save that on the stack
2) Fetch up the compiled code for the undecorated function
3) Grab the name of the function (it's a constant)
4) Create a function. Don't save it anywhere yet, just put it on the stack.
5) Call the function from step 1, passing the function from step 4 as
a parameter.
6) Whatever it returns, save that under the name "celsius".
That's very detailed and nitty-gritty, but that's what really happens
when you use "@celsius.setter" in your code.
ChrisA
More information about the Python-list
mailing list