Steven D'Aprano <[EMAIL PROTECTED]> 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". The tests here are not 100% reliable, of course -- in 2.0, a dict which just happens to have a 0 key would erroneously pass; but short of actually trying the loop, there's no infallible way that I know of. One possibility (that I haven't tried in real life) to deal with the hellish situation of having to write code that's able to loop on an iterable but fail softly otherwise, while not hiding errors in the loop's body, would be the suitably hellish...: class NotATypeError(Exception): def __init__(self, e, t): self.e = e self.t = t try: try: for item in whatever: try: ...loop body here... except TypeError, e, t: raise NotATypeError(e, t) except TypeError: ....fail-softly code... except NotATypeError, x: raise TypeError, x.e, x.t This kind of spaghetti code is what gives backwards compatibility its bad name, of course. Be sure that you're getting paid for this in proportion to its ugliness, and your finances should be set for life. Alex -- http://mail.python.org/mailman/listinfo/python-list