[Python-Dev] Re: Writing a mutable object problem with __setattr__

Aleksandar Totic atotic@osafoundation.org
Tue, 25 Feb 2003 08:55:45 -0800


Guido van Rossum wrote:
 > Aleks Totic wrote:
>>I am trying to create a mutable object for a persistent object 
>>database, and I've ran into a problem. The semantics are:
>>
>>Object gets created as a 'Swizzle'. Swizzle is a stub that 
>>intercepts any attempt to access object properties. When code 
>>tries to access any of swizzle's properties, the swizzle should 
>>automatically mutate into the stored object, by changing its 
>>class and properties.
> 
>  .....................................
> 
>>With the __set/get/del/attr__ traps this seemed feasible in 
>>Python. But it turns out to be trickier than I've thought, my 
>>naive implementation is not working.
>>
>>What happens is:
>>swizzle.__getattr__() gets called
>>   calls swizzle.load()
>>     swizzle.__class__ = stored_class
>>     swizzle.__dict__ = stored_data
>>   calls getattr(self, attr_name)
>>   calls swizzle.__getattr__() gets called
>>     and I enter an infinite loop and blow the stack
>>
>>
>>I've tried many different approaches:
>>- Swizzle inheriting from object (so that I can call super 
>>methods directly). This one would not let me assign into the 
>>__class__
>  
> In Python 2.2.2 you can set __class__, as long as __class__ has a
> compatible instance lay-out (at the C implementation level).

This is the part where I am confused. How do I know if something 
is an old or new style object? Do new-style objects derive from 
built-in types (object/dict..)

> With new-style objects, you can use __getattribute__ instead of
> __getattr__ for more control (and also more opportunities to blow the
> stack :-).
 >
 >.................................
 >
>>     def __setattr__(self, name, value):
>>         """ setattr passes class & dict because these are called
>>         when we are mutating the object """
>>         print "swizzle setattr called"
>>         if (name == '__class__' or name == '__dict__' or name == 
>>'oid'):
>>             self.__dict__[name] = value
>>             return
> 
> 
> Ah, here's the catch.  You can't implement assignment to __dict__ or
> __class__ by doing "self.__dict__[name] = value".
> 
> Use new-style classes and you'll be much happier: you can invoke the
> superclass __setattr__ to do the magic.

I've tried this, but then I was unable to create any of the 
old-style classes. Is there any solution that would let me mutate 
an object into both? I suspect not. Then the question is:

- is there a runtime/compiling python flag to force all objects 
into new-style layout? This will be the future, I think I've read 
somewhere.

- how can I tell the difference between old and new programatically?

Aleks