On Tuesday 20 September 2005 12:31, ago wrote:
Is it possible to have a default value associated python objects? I.e.
to flag an attribute in such a way that the assignment operator for the
object returns the default attribute instead of the object itself, but
calls to other object attributes are properly resolved? (I don't think
so, but I am not sure)
I was thinking about this last night and it seemed an interesting problem. I
thought you might want to change the way you look at it, using the python
equivalent to type casting (maybe its called "coercing", sorry for my poor
command of python vocabulary). I have overridden __int__ and __float__ for
this example. You might want to look into __coerce__. This should have the
behavior you desire while having the explicit syntax expected of good python
code.
Inheriting from list allows you to use a stack-like behavior you described in
a previous email. You can further modify __getattribute__, __setattribute__,
__delattribute__, etc. Overriding __iter__ gives you the history in "correct"
order, but may begin to embark on a non-intuitive interface--you be the
judge. I think this is about as close as you can get in python to what you
are thinking (don't know the oldest python version this is backwards
compatible with):
py> class Thing(list):
.... def __init__(self, start_value):
.... list.__init__(self)
.... self.append(start_value)
.... def __setattr__(self, anattr, aval):
.... if (anattr == 'top'):
.... self.append(aval)
.... else:
.... list.__setattr__(self, anattr, aval)
.... def __getattr__(self, anattr):
.... if (anattr == 'top'):
.... return self[-1]
.... elif (anattr == 'old'):
.... try:
.... return self[-2]
.... except IndexError:
.... raise NameError, "No old value yet"
.... else:
.... list.__getattr__(self, anattr)
.... def __iter__(self):
.... return list.__iter__(self[::-1])
.... def __int__(self):
.... return int(self.top)
.... def __float__(self):
.... return float(self.top)
.... def __str__(self):
.... return str(self.top)
....
py> athing = Thing(5) # should init with a reasonable value
py> athing.top # __getattr__
5
py> int(athing) # __int__
5
py> print athing # __str__
5
py> float(athing) # __float__
5.0
py> athing.top = 4 # __setattr__
py> print athing
4
py> athing.old # __getattr__
5
py> athing.top = 42 # __setattr__
py> [x for x in athing] # __iter__
[42, 4, 5]
py> y = float(athing) # closest you can get to assignment overloading
py> print y # y is a float
42.0
py> athing # Thing inherits from list, so you get list.__repr__() here
[5, 4, 42]
Here it is without the prompts:
class Thing(list):
def __init__(self, start_value):
list.__init__(self)
self.append(start_value)
def __setattr__(self, anattr, aval):
if (anattr == 'top'):
self.append(aval)
else:
list.__setattr__(self, anattr, aval)
def __getattr__(self, anattr):
if (anattr == 'top'):
return self[-1]
elif (anattr == 'old'):
try:
return self[-2]
except IndexError:
raise NameError, "No old value yet"
else:
list.__getattr__(self, anattr)
def __iter__(self):
return list.__iter__(self[::-1])
def __int__(self):
return int(self.top)
def __float__(self):
return float(self.top)
def __str__(self):
return str(self.top)
--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095
http://www.jamesstroud.com/