Case Statements

Steven D'Aprano steve+comp.lang.python at pearwood.info
Thu Mar 17 02:29:35 EDT 2016


On Thursday 17 March 2016 16:45, Gregory Ewing wrote:

> Steven D'Aprano wrote:
>> On Thu, 17 Mar 2016 11:31 am, Chris Angelico wrote:
>> 
>>>    orig = globals()[cls.__name__]
>> 
>> I wouldn't want to rely on it working with decorator syntax either. Even
>> if it does now, I'm not sure that's a language guarantee.
> 
> The following idiom relies on similar behaviour:
> 
>      @property
>      def x(self):
>          return self._x
> 
>      @x.setter
>      def x(self, value):
>          self._x = value
> 
> That's taken from the official docs, so I don't think
> this is likely to change any time soon.


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.

What happens if you use different names?

@property
def x(self):
    pass

@x.setter
def y(self, arg):
    pass


Now you have two different properties:

py> x
<property object at 0xb756eb1c>
py> y
<property object at 0xb756ef04>


Both x and y's getter points to the same function (our original def x):

py> y.fget
<function x at 0xb7564a04>
py> x.fget
<function x at 0xb7564a04>


But x's setter is None, while y has a valid setter:

py> x.fset is None
True
py> y.fset
<function y at 0xb7582ca4>


I don't think that either x or y will misbehave, but the behaviour will 
certainly be surprising if you're not expecting it.

I think the documentation in Python 2.7 is misleading. help(x.setter) says:

setter(...)
    Descriptor to change the setter on a property.

which is, I believe, a lie. It doesn't "change the setter" (modify the 
property object in place), but returns a new property object. Here's my 
pseudo-code for what I think property.setter does:

class property:
    def setter(self, func):
        return property(self.fget, func, self.fdel, self.__doc__)



As far as I can tell, none of this behaviour relies on the decorator being 
called before the name of the decorated thing is bound.




-- 
Steve




More information about the Python-list mailing list