is_iterable function.
Neil Cerutti
horpner at yahoo.com
Thu Jul 26 11:02:39 EDT 2007
Based on the discussions in this thread (thanks all for your
thoughts), I'm settling for:
def is_iterable(obj):
try:
iter(obj).next()
return True
except TypeError:
return False
except KeyError:
return False
The call to iter will fail for objects that don't support the
iterator protocol, and the call to next will fail for a
(hopefully large) subset of the objects that don't support the
sequence protocol.
This seems preferable to cluttering code with exception handling
and inspecting tracebacks. But it's still basically wrong, I
guess.
To repost my use case:
def deeply_mapped(func, iterable):
""" Recursively apply a function to every item in a iterable object,
recursively descending into items that are iterable. The result is an
iterator over the mapped values. Similar to the builtin map function, func
may be None, causing the items to returned unchanged.
>>> import functools
>>> flattened = functools.partial(deeply_mapped, None)
>>> list(flattened([[1], [2, 3, []], 4]))
[1, 2, 3, 4]
>>> list(flattened(((1), (2, 3, ()), 4)))
[1, 2, 3, 4]
>>> list(flattened([[[[]]], 1, 2, 3, 4]))
[1, 2, 3, 4]
>>> list(flattened([1, [[[2, 3]], 4]]))
[1, 2, 3, 4]
"""
for item in iterable:
if is_iterable(item):
for it in deeply_mapped(func, item):
if func is None:
yield it
else:
yield func(it)
else:
if func is None:
yield item
else:
yield func(item)
--
Neil Cerutti
More information about the Python-list
mailing list