Reputation: 16526
I know that my question seems to be very similar to others. but it's not actually, I've searched a lot and couldn't find my answer.
As we know:
@mydecorator
def myfn():
pass
is (exactly?) translated to :
def myfn():
pass
myfn = mydecorator(myfn)
consider the following class:
class C:
def __init__(self, language):
self._language = language
@property
def language(self):
return self._language
@language.setter
def language(self, value):
self._language = value
if we want to translate these to the function + assignment statement, for the getter there is no problem:
def language(self):
return self._language
language = property(language)
but what about setter? :
def language(self, value):
self._language = value
language = language.setter(language)
I did exactly what I had done before but that's not going to work. after the previous stage(getter), label 'language' refered to the property object. now it's reassigned to a function(function comes first)! so this language.setter isn't going to work it's not a property anymore.
I thought maybe there is an extra step when we use @ syntax. if it is, what is that? and can we say they are roughly similar to each other.
if it's not, for example when we use decorator with property objects they behave a bit more than just translation into function + assignment statement ?
Upvotes: 6
Views: 526
Reputation: 24242
The difference is exactly where you asked yourself if it was (exactly?)
the same.
PEP 318 mentions it rapidly:
Current Syntax
The current syntax for function decorators as implemented in Python 2.4a2 is:
@dec2
@dec1
def func(arg1, arg2, ...):
pass
This is equivalent to:
def func(arg1, arg2, ...):
pass
func = dec2(dec1(func))
without the intermediate assignment to the variable func. (emphasis mine)
So, that's why everything works fine when you use the @decorator
syntax.
You could make it work by using a different name:
class C:
def __init__(self, language):
self._language = language
def language(self):
return self._language
language = property(language)
def dummy_temporary_name(self, value):
self._language = value
language = language.setter(dummy_temporary_name)
c = C('fr')
print(c.language)
c.language = 'de'
print(c.language)
# fr
# de
Upvotes: 2