I was writing some tests for a mapping class I have made, and I decided to run those same tests over dict and UserDict. The built-in dict passed all the tests, but UserDict failed one:
class SimpleMappingTest(unittest.TestCase): type2test = UserDict.UserDict def test_iter(self): k, v = [0, 1, 2, 3], 'abcd' m = self.type2test(zip(k, v)) it = iter(m) self.assert_(iter(it) is it) self.assertEquals(sorted(it), k) # This line fails. # many more tests To cut a long story short, the problem is that UserDict doesn't support the modern iteration protocol. Python falls back on the old-fashioned __getitem__ iteration protocol, but since it expects IndexError rather than KeyError, iteration fails for UserDict once it hits key=4. If I look at the source code for the UserDict module, I discover that there's a second mapping class, IterableUserDict, specifically to make UserDict iterable. To do this requires a single one-line method: class IterableUserDict(UserDict): def __iter__(self): return iter(self.data) This class was apparently added to the module in 2.2 -- it doesn't exist in 2.1. Now that boggles my brain. Why was support for iteration added as a subclass, instead of simply adding the __iter__ method to UserDict? UserDict is supposed to be a drop-in replacement for dict (although the use-cases for it are much fewer now that we can inherit from dict), so it doesn't make sense to me to have a non-iterable UserDict plus a subclass which is iterable. Can anyone shed any light on this apparently bizarre design decision? -- Steven -- http://mail.python.org/mailman/listinfo/python-list