jez jez - 6 months ago 11
Python Question

property fset function not getting called

I can't work out what I've started doing wrong here. I've always initialized managed class properties with

property( fget=fget, fset=fset )
and I have a memory that both my getters and my setters used to work in both Python 2 and 3. Now, using code practically straight out of the official documentation, I'm finding that my getters work, but my setter functions appear to be ignored in Python 2.x - assignment to the property just wipes out its propertyness and replaces it with a vanilla attribute. All is well in Python 3.x, however. What am I doing wrong?

class foo:
def getcode( self ): return self.__code
def setcode( self, value ): self.__code = value.upper()[ : 1 ]
def delcode( self ): raise AttributeError( "cannot remove the 'code' property" )
code = property( fget=getcode, fset=setcode, fdel=delcode, doc='A single upper-case character' )

def __init__( self, code='A' ): self.setcode( code )

f = foo(); f.code = 'A'
print( f.code ) # expect 'A', get 'A'
f = foo(); f.code = 'bbb'
print( f.code ) # expect 'B' but python 2.7.10 prints 'bbb'
f = foo(); f.code = 5 # expect an exception but python 2.7.10 does not raise one
print( f.code )

Answer

By default, Python 2.x classes do not inherit from object, which makes the distinction between old style classes and new style classes introduced by Python >2.2.

property() is a succinct way of building a data descriptor that triggers function calls upon access to an attribute, however it fully works as described in documentation here for new-style classes only: class has to inherit from object.