[Python-3000] Iterators for dict keys, values, and items == annoying :)
Tim Peters
tim.peters at gmail.com
Sat Mar 25 03:22:39 CET 2006
[Tim]
>> ...
>> There's one other common surprise in Zope-land, namely that
>>
>> for key in b.keys():
>> ... possibly try to delete `key` from `b`
>>
>> "doesn't work" when `b` is a BTree. The _expectation_, derived from
>> experience with Python dicts, is that it's bulletproof, but that's
>> again because dict.keys() has returned a distinct list and BTrees were
>> just different that way.
[Guido]
> The Java collections framework actually has an API and an idiom that
> make this work: therd's a method on the *iterator* that deletes the
> current item without disturbing the iteration.
Yup, I saw that:
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Iterator.html
It's at least curious that there isn't also a method to add an item in
the base Iterator interface.
> The iterator is required to maintain enough state to know whether
> deletion is currently valid -- it's not before you've started iterating, or after
> the iterator is exhausted, or if you've already deleted the item.
> Deleting the item does not automatically move to the next item; you
> must still call next() for that.
Or, even easier, it can just throw UnsupportedOperationException if it
doesn't feel like implementing Iterator.remove() in a useful way :-)
> Clearly this requires careful cooperation between the iterator and the
> container! For Python sets and dicts, it would be sufficient to
> guarantee not to rehash upon such a deletion. For lists, it would
> require the iterator to remember not to increment the index on the
> subsequent next() call.
Iterator.remove() would be reasonably easy to implement for BTrees
too, given the Java constraint that all bets are off if the
collection is modified in any way other than via Iterator.remove().
> Java has a few flavors of iterators; for lists it also has an extended
> iterator that allows moving back, and of course it also has iterators
> that don't support deletion for whatever reason. It's a really neat
> API!
On the page referenced above, ListIterator is given as the only
"known" subinterface of Iterator. Iterators that don't want to
support remove() still implement the base Iterator interface, but take
the UnsupportedOperationException dodge noted above.
> Note that this is all quite independent from the views proposal (also
> inspired by Java).
I'm not sure I saw a coherent "views proposal" ;-) Java has some nice
ideas, but I'd think it's too elaborate for your tastes (and, by
extension, for Python's). For example, it has six(?) collection
interfaces, two of which don't even extend the base Collection
interface. AFAICT, what Java calls "views" are unique to some methods
of its Map and SortedMap interfaces.
To be concrete, is what you're calling "a view" the kind of thing
returned by Java's AbstsactMap.entrySet()?:
http://java.sun.com/j2se/1.4.2/docs/api/java/util/AbstractMap.html
That's closest to Python's items(), and AbstractMap.keys() is closest
to Python's keys(). Java being Java, AbstractMap.values() returns a
different _type_ of object than those two (Java's further
sub-distinction between "set views" and "collection views").
I vote to steal the good parts and drop all the distinctions :-)
More information about the Python-3000
mailing list