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 said:
Terry said:
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