Thomas Olsen wrote:
Hi
I'm working on a CMF Product which is based on PortalFolder and PortalContent. This Folderish object contains some items which inherits from OFS.SimpleItem.Item, Persistence.Persistent and Aquisition.Implicit. These items have (had) some properties which are speciel to their class. In order to get around the problem with adding new attributes and having instantiated objects which doesn't have the attributes I decided to keep the attributes in a dictionary. So in my base class I did:
---snip-------------------------------------------- class AbstractElement(Persistent, Item, Implicit): """ Abstract base class for Element objects. """ _attributes = PersistentMapping()
def __getattr__(self, name): if self._attributes.has_key(name): return self._attributes[name] else: raise AttributeError, name ---snip--------------------------------------------
Note that this spelling make '_attributes' a "shared instance attribute" (all instances of the class, or ony class derived from it, will share the mapping. Normally, I would expect to see the '_attibutes' assigned either in the initializer:: def __init__( self ): self._attributes = PersistentMapping() or else "lazily":: _attributes = None; def __getattr__( self, name ): if self._attributes is None: self._attributes = PersistentMapping() if self._attributes.has_key( name ): #...
and my derived classes look something like this:
---snip-------------------------------------------- class TextElement(AbstractElement): """ text element. """ meta_type = 'Text Element'
def __init__(self, id): self.id = id self._attributes = {'value':'','html':'','alignment':''}
def edit(self, value, html, alignment): """ Update the properties """ self._attributes['alignment'] = str(alignment) self._attributes['value'] = str(value) self._attributes['html'] = utils._format_stx(self.value) ---snip--------------------------------------------
It works great - until the object gets unloaded from the memory :-(
What am I doing wrong?
Note as well that plaing with '__getattr__' in the presence of the acquisition machinery could be classifieds as Deep Voodoo (tm); The canonical solution to your problem is to set a "shared" value for the new attribute on the class, with an appropriate default; instances which don't have the attribute in their own '__dict__' will find it in the class. Where that solution is infeasible, the pickling machinery offers the '__setstate__' hook, which is called immediately on unpickling; you would *really* prefer not to use this hook, but it is available. Tres. -- =============================================================== Tres Seaver tseaver@zope.com Zope Corporation "Zope Dealers" http://www.zope.com