is parameter an iterable?

Roy Smith roy at panix.com
Wed Nov 16 17:47:17 EST 2005


Steven D'Aprano  <steve at REMOVETHIScyber.com.au> wrote:
># Create an instance of the exception you expect:
>try:
>    for i in 0:
>        pass
>except TypeError, ITER_OVER_NON_SEQ:
>    pass
># Now run your code...
>try:
>    ...blah blah blah...
>except TypeError, msg
>    if str(msg) == str(ITER_OVER_NON_SEQ):
>        ...blah blah blah... 
>
>This means we're no longer assuming what the error message will be,
>which makes our code a lot more future-proof and implementation-proof: if
>some version of Python changes the error string from "iteration over
>non-sequence" to something else, the code should continue to work
>correctly.

Now you're assuming that the message is a constant for all TypeErrors
caused by attempting to iterate over a non-iterable object.  I don't
see anything in the docs which prevents

try:
  for i in 0:
    pass
except TypeError, ex:
  print ex

from printing "Cannot iterate over integer with value 0", or even
"Cannot iteratate over object at address <0x456778>".  Let's not even
talk about some future implementor who decides that the strings should
contain timestamps.  None of these things are forbidden by the spec,
therefore you should assume they will all happen.

The best solution I've seen suggested so far is to coerce the
passed-in object to an iter and see what happens:

try:
  thingieIterator = iter (thingie)
except TypeError:
  raise NonIterableThingieError

Once you've done that, I think you can either do:

for item in thingie:

or

for item in thingieIterator:

with equal effect.  And I'm reasonably sure this will work fine with
non-idempotent thingies.



More information about the Python-list mailing list