On 2/14/06, Peter Bengtsson <[EMAIL PROTECTED]> wrote: > D'oh! That's confusing. Isn't there a class that gathers all of these in one. > > It seems confusing, you derive from Persistent but only some are accepted. > Does that mean that there's PersistentFloat and PersistentTuple too? > If not, why *only* dicts?
As mentioned above, it applies to *mutable* objects. """ Objects whose value can change are said to be mutable; objects whose value is unchangeable once they are created are called immutable. (The value of an immutable container object that contains a reference to a mutable object can change when the latter's value is changed; however the container is still considered immutable, because the collection of objects it contains cannot be changed. So, immutability is not strictly the same as having an unchangeable value, it is more subtle.) An object's mutability is determined by its type; for instance, numbers, strings and tuples are immutable, while dictionaries and lists are mutable. """ http://docs.python.org/ref/objects.html Instances of Persistent based classes know when they change. Like if you do:: clive.age = 28 Which is effectively ``setattr(clive, 'age', 28)``. As a persistent object, clive notices that an attribute is being set (even if it's replacing an existing value), and flags that 'clive' has changes that need to be saved. So again - here, it's the 'clive' object that's being updated in this case. The fact that the value is an integer doesn't matter. It's not changing. 28 is 28. But 'clive' is changing by having a new/updated 'age' attribute set. On the other hand, if you do:: clive.favoriteNumbers.append(13) 'clive' does not change. 'favoriteNumbers' changes. If favoriteNumbers is a regular Python list, the persistence machinery has no idea that it's changed. It's not being assigned to 'clive', it's already an attribute there and is not being replaced. So if it's not a PersistentList, it gets forgotten. If favoriteNumbers was a tuple, you couldn't append to it. You could do an addition, but in a form like this:: clive.favoriteNumbers = clive.favoriteNumbers + (13,) # Alternately clive.favoriteNumbers += (13,) This is doing assignment. 'clive' is getting a new attribute set, and as a Persistent object 'clive' can be set as needing its changes saved. It's not only dicts, it's dicts and lists (PersistentDict and PersistentList). I don't know if there's a PersistentSet. Python offers two sets since 2.3 - a mutable (list-like) one and an immutable (tuple-like) one. I imagine that if you use the mutable set (``sets.Set`` in 2.3, ``set`` in 2.4), you'd run into the same problems. But if you used the immutable set (``sets.ImmutableSet``, ``frozenset`` in 2.4) you wouldn't. Note that this issue affects not just ZODB persistence. If you used even the simple 'shelve' module that's in Python, you have the same issue unless you use a 'writeback' option: """ If the writeback parameter is True, the object will hold a cache of all entries accessed and write them back to the dict at sync and close times. This allows natural operations on mutable entries, but can consume much more memory and make sync and close take a long time. """ So as a way of making working with default mutable objects feel natural, this option makes shelve read and write its whole database, which would obviously be very expensive for the ZODB. So - just use PersistentList and PersistentDict (or look into BTrees for better storage options). For more details, visit the ZODB documentation on ZODB programming, and visit the section on modifying mutable objects: http://www.zope.org/Wikis/ZODB/FrontPage/guide/node3.html _______________________________________________ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users