docs on for-loop with no __iter__?

Alex Martelli aleaxit at yahoo.com
Tue Sep 7 11:32:44 CEST 2004


Steven Bethard <steven.bethard at gmail.com> wrote:
   ...
> If you've provided a __len__ method and a __getitem__ that returns items for
> each index, then you've already provided all the necessary information for
> iteration.  If the __getitem__ also has to raise an IndexError when the index
> exceeds the length, in some sense, you're duplicating information -- both
> __len__ and the IndexError tell you the length of the sequence.  So it's not
> an exception fear, but a duplication of code fear, which I hope is somewhat
> more Pythonic. =)
> 
> It would have made describing the protocol somewhat more complex, but it would
> have made using the protocol in a class simpler.  Moot point of course, since
> I'm fully convinced that changing the protocol is infeasible. =)

We do agree the point is moot, but we deeply disagree on the point
itself.

__getitem__ has to raise IndexError for invalid indices -- that's part
of its job.  Now we're not talking just about iteration anymore, but any
kind of indexing.  Having the existence of __len__ interfere with how or
whether __getitem__ gets called would just substantially complicate
things, particularly considering that both exist for mappings as well as
for sequences.  It may look superficially "convenient" to lighten your
_getitem__'s burden by wishing it would only be called for "good"
indices, but it's really an optical illusion.

As for having __getitem__ sometimes called unconditionally (whether
__len__ is there or not) and sometimes conditionally (when either
__len__ is absent, or, if present, then only for indices that appear to
be correct depending on __len__'s return value) -- this way madness
lies.  Attempts to make things "convenient" in this way are behind the
almost inevitable bloating of all languages whose design principles
don't put simplicity high enough on the list.  "Special cases are not
special enough to break the rules".  When moving to Python from other
languages, this kind of dynamic tension between mere convenience and
conceptual simplicity is quite an important thing to keep in mind, if
one is keen about understanding in depth various aspects of its design
(and you do appear to be just the kind of person who values such
in-depth understanding -- I'm also very much like that, myself) -- which
is why I'm trying to explain my mental model for why that particular
design aspect, even though not all that relevant today, was indeed an
excellent choice (note that I have no bias in the matter -- that
protocol was in Python well before I knew what Python was!-).

It's partly a matter of "look before you leap" versus "easier to ask
forgiveness than permission", a conceptual distinction that IS quite a
hobby-horse of mine (although "practicality beats purity", mind you;-).


Alex
 



More information about the Python-list mailing list