[Zope-Coders] Fw: [Zope] sessions and zope2.6.0

Tim Peters tim@zope.com
Tue, 22 Oct 2002 12:37:26 -0400


FYI, here's an example:

>>> t = IIBTree()
>>> for i in range(100):
...     t[i] = i
...

>>> for k in t.keys(None, 20):
...     del t[k]  # Bad Idea to mutate while iterating
...

>>> list(t.keys()) # oops
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33,
 35, 37, 39, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]

>>> t = IIBTree()
>>> for i in range(100):
...     t[i] = i
...
>>> for k in list(t.keys(None, 20)):
...     del t[k]   # OK if iterating over a distinct list of keys
...
>>> list(t.keys())
[21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>>

In effect, in the first example the initial t.keys() object points into
"internal slot number 0".  It gets the first key and updates its pointer to
"internal slot number 1".  del t[k] then physically deletes the key at slot
#0, and physically *moves* all the keys in the first bucket left one slot.
So what *was* in slot #1 (the integer 1) moves into slot #0, and the
iterator object will never look at slot #0 again, so the key 1 survives.
OTOH, what was in slot #2 (the integer 2) moves into slot #1, and so that's
the key the iterator sees the next time around.  Etc.  It's an unpredictable
mess, and at internal bucket boundaries the seemingly regular pattern breaks
down (because it's not the entire BTree that "shifts a slot to the left"
when a delete happens, it's only the bucket containing the key being deleted
that shifts left).