Why IterableUserDict?
Steven D'Aprano
steve at REMOVE-THIS-cybersource.com.au
Fri Sep 17 23:12:15 EDT 2010
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
More information about the Python-list
mailing list