Backwards compatibility [was Re: is parameter an iterable?]

Fredrik Lundh fredrik at pythonware.com
Tue Nov 22 02:33:04 EST 2005


Alex Martelli wrote:

> > In the specific case of iter(), are there good
> > alternative ways of detecting an iterable without
> > consuming it?
>
> Not a problem I've had often, but when I did, if I recall correctly, I
> did something like:
>
> try:
>   iter
> except NameError:
>   def isiterable(x):
>     try: x[0]
>     except Exception: return 0
>     else: return 1
> else:
>   def isiterable(x):
>     try: iter(x)
>     except TypeError: return 0
>     else: return 1
>
> Not True/False because they wouldn't be available in 2.0 any more than
> iter would.  "Consuming" didn't really come into consideration for the
> backwards compatibility part because only objects indexable with
> integers, 0 and up (and raising IndexError at some point) were usable in
> for statements in old Pythons, there was no "consuming".

Before the iterator protocol was added, using the sequence protocol
to implement "forward-only iterators" weren't uncommon. e.g.

    class my_file_iterator:
        def __init__(self, file):
            self.file = file
        def __getitem__(self, index):
            line = self.file.readline()
            if not line:
                raise IndexError
            return line

(for extra points, add code that makes sure that the index matches
the line number)

To test for this, you could look for __getitem__ methods on instance
objects, and use operator.isSequenceType on everything else, but that
doesn't distinguish between sequences and mappings.

> short of actually trying the loop, there's no infallible way that I know of.

Exactly.  And iter() can fail too, even if it's far less likely that you
stumble upon an iterable that misbehaves if you call __iter__ one
extra time.  Which is why the portable pragmatic pythonic solution
is to design your program so it doesn't depend on type/interface
testing.

If you want to loop over things, loop over things, and leave it to
Python to raise an exception if you get something that doesn't
support looping.

And unless you have very good reasons, you should treat that
exception as a bug in your program.

</F>






More information about the Python-list mailing list