On Tue, 15 Nov 2005 11:26:23 -0800, py wrote: > Dan Sommers wrote: >> Just do it. If one of foo's callers passes in a non-iterable, foo will >> raise an exception, and you'll catch it during testing > > That's exactly what I don't want. I don't want an exception, instead I > want to check to see if it's an iterable....if it is continue, if not > return an error code. I can't catch it during testing since this is > going to be used by other people.
That would be the Look Before You Leap school of thought. That is rarely the best way of doing things in Python. (Note I said *rarely*, not *never*.) If you insist, you would have to do something like this: def is_iterable(obj): """Returns True if obj is *probably* an iterable and False otherwise. Not that some weird custom objects that break the rules may give incorrect results. """ if type(obj) in (type([]), type(()), type("")): return True elif hasattr(obj, next) and callable(obj.next): return True elif hasattr(obj, __getitem__): return True else: # I don't think I missed anything... return False But in fact there is an easier way: def is_iterable(obj): """Just Do It.""" try: for item in obj: break except TypeError: return False return True That works, but it has a side-effect: if you pass it an iterable that gets consumed, you now have used up the first item of it (e.g. if you a reading lines from a file, you've just used the first line and won't get it back unless you reset the file pointer). So do your test inside your code: def foo(inputVal): try: for val in inputVal: # do stuff except TypeError, msg: if msg == "iteration over non-sequence": # handle non-iterable case else: # some other TypeError is a bug, so re-raise the exception raise -- http://mail.python.org/mailman/listinfo/python-list