On Thu, Feb 9, 2017 at 6:03 PM, ast <nomail@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 -- https://mail.python.org/mailman/listinfo/python-list