__peter__ at web.de
Sat Sep 18 09:42:14 CEST 2010
Steven D'Aprano wrote:
> 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?
I looked it up for you:
Revision 22248 - (view) (download) (as text) (annotate) - [select for diffs]
Modified Tue Aug 7 17:40:42 2001 UTC (9 years, 1 month ago) by gvanrossum
File length: 1913 byte(s)
Diff to previous 21167
Remove the __iter__ method from the UserDict class -- it can silently
break old code (in extreme cases). See SF bug #448153.
Add a new subclass IterableUserDict that has the __iter__ method.
Note that for new projects, unless backwards compatibility with
pre-2.2 Python is required, subclassing 'dictionary' is recommended;
UserDict might become deprecated.
The bug report is also interesting:
More information about the Python-list