Object default value

James Stroud jstroud at mbi.ucla.edu
Wed Sep 21 18:31:28 EDT 2005


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/



More information about the Python-list mailing list