Testing for the '__iter__' (or even '__getitem__') attribute doesn't really address the problem, nor does trying to execute the statement 'itr = iter(a)'.
To use EAPF and answer the OP's original question, which was > So how can I test if a variable 'a' is either a single character > string or a list? I think the best answer would be to use Robin Munn's suggestion (see http://groups-beta.google.com/group/comp.lang.python/msg/c8befd4bed517bbc) as mentioned in the link in Simon Brunning's post) namely: try: a + '' except TypeError: pass else: a = [a] However, to handle the more general problem of allow *any* argument to be either a single item or a list seems to require a combination of both EAPF and LBYL. This is the best solution I've been able to come up with so far: def asList(arg): """Makes sure the argument it is passed is a Python list. If it is, it is just returned, otherwise a (possibly empty) list is created and returned with the single item in it. asList() can used to create flexible interfaces which allow arguments to be passed to them that are either single items or lists of items. By applying this function before using the values in arguments, single and multi-valued cases can be handled by general list-handling code in the function or method. As a special case, a single argument with the value None is converted into an empty list (instead of converted into the list [None]). asList(arg) ==> list """ if arg is None: return [] elif isinstance(arg, basestring): # special case strings (to # avoid list(<string>)) return [arg] else: try: return list(arg) except TypeError: return [arg] if __name__ == "__main__": def example(items=None): """Sample function that can be called with a single argument that can be a single or list of items. """ itemList = asList(items) if not itemList: print "example() called with empty list or None argument" else: print "example() called with argument containing %d " \ "thing%s" % \ (len(itemList), ('','s')[len(itemList)>1]) for i, item in enumerate(itemList): print " items[%d] = %s" % (i, repr(item)) example(42) example((1,2,3)) example([4,5,6,7]) example('abc') example(u'def') example(["aaa", 111, (4,5), 2.01]) example(None) # Note that this will become an empty list example() # same in this case Which produces the following output: example() called with argument containing 1 thing items[0] = 42 example() called with argument containing 3 things items[0] = 1 items[1] = 2 items[2] = 3 example() called with argument containing 4 things items[0] = 4 items[1] = 5 items[2] = 6 items[3] = 7 example() called with argument containing 1 thing items[0] = 'abc' example() called with argument containing 1 thing items[0] = u'def' example() called with argument containing 4 things items[0] = 'aaa' items[1] = 111 items[2] = (4, 5) items[3] = 2.0099999999999998 example() called with empty list or None argument example() called with empty list or None argument Can this be improved or is there anything wrong or overly limiting about it? TIA, Martin ===================== Steven Bethard wrote: > Terry Hancock wrote: > > But you probably shouldn't do that. You should probably just test to > > see if the object is iterable --- does it have an __iter__ method? > > > > Which might look like this: > > > > if hasattr(a, '__iter__'): > > print "'a' quacks like a duck" > > Martin Miller top-posted: > > I don't believe you can use the test for a __iter__ attribute in this > > case, for the following reason: > > > >>>>c1 = 'abc' > >>>>c2 = ['de', 'fgh', 'ijkl'] > >>>>hasattr(c1, '__iter__') > > False > > > >>>>hasattr(c2, '__iter__') > > True > > Right. str and unicode objects support iteration through the old > __getitem__ protocol, not the __iter__ protocol. If you want to use > something as an iterable, just use it and catch the exception: > > try: > itr = iter(a) > except TypeError: > # 'a' is not iterable > else: > # 'a' is iterable > > Another lesson in why EAPF is often better than LBYL in Python[1]. > > STeVe > > [1] http://www.python.org/moin/PythonGlossary -- http://mail.python.org/mailman/listinfo/python-list