undesired interraction between property and __setattr__
dman
dsh8290 at rit.edu
Sat Jan 26 14:25:20 EST 2002
Hi All, I'm back :-).
I'm doing some work with version 2.2 and found that the new property()
feature is just what I'm looking for for part of my work. The old
__setattr__ is what I want for the rest. However, I found an
undesired interraction between the two. This code snippet shows what
happens :
~~~~~~~~~~~~~~~~~~~~
class Struct( object ) : pass
class C( object ) :
def __init__( self ) :
self._s = Struct()
def getx( self ) :
print "getx!"
return self._s.the_x
def setx( self , value ) :
print "setx!" , value
self._s.the_x = value
x = property( getx , setx )
def __setattr__( self , name , value ) :
if name == "_s" :
self.__dict__[name] = value
else :
print name , "=>" , value
setattr( self._s , name , value )
o = C()
o.x = 1
~~~~~~~~~~~~~~~~~~~~
The "Struct" class is just a stand-in to make the example shorter. In
reality I want to enhance an existing class using composition (hence
the __(get|set)attr__ pair, though get isn't shown here). For some of
the attributes, however, I want to rename them or add additional
functionality. For those, "properties" are the right solution. The
problem is that the setx() method is never called.
Through googling I found this message by Tim Peters :
http://groups.google.com/groups?hl=en&selm=mailman.1002067383.24001.python-list%40python.org
that explains how the properties thing actually works. (Thanks Tim.
The documentation I was able to find is a bit parse and magical :-))
This led me to the following "solution" :
~~~~~~~~~~~~~~~~~~~~
class Struct( object ) : pass
class C( object ) :
def __init__( self ) :
self._s = Struct()
def getx( self ) :
print "getx!"
return self._s.the_x
def setx( self , value ) :
print "setx!" , value
self._s.the_x = value
x = property( getx , setx )
def __setattr__( self , name , value ) :
if name == "_s" :
self.__dict__[name] = value
elif name in self.__class__.__dict__ :
self.__dict__[ name ] = self.__class__.__dict__[ name ]
self.__dict__[ name ].__set__( self , value )
else :
print name , "=>" , value
setattr( self._s , name , value )
o = C()
o.x = 1
~~~~~~~~~~~~~~~~~~~~
Notice the extra 'elif' in __setattr__. I haven't tested it
thoroughly (what happens if a name is duplicated or something?), but
it works in the correct case.
Is this the proper/ideal solution, or is there something I'm missing,
or is this a bug in python?
TIA,
-D
--
Q: What is the difference betwee open-source and commercial software?
A: If you have a problem with commercial software you can call a phone
number and they will tell you it might be solved in a future version.
For open-source sofware there isn't a phone number to call, but you
get the solution within a day.
More information about the Python-list
mailing list