53 lines
1.4 KiB
Python
53 lines
1.4 KiB
Python
|
# from more_itertools 10.2
|
||
|
def always_iterable(obj, base_type=(str, bytes)):
|
||
|
"""If *obj* is iterable, return an iterator over its items::
|
||
|
|
||
|
>>> obj = (1, 2, 3)
|
||
|
>>> list(always_iterable(obj))
|
||
|
[1, 2, 3]
|
||
|
|
||
|
If *obj* is not iterable, return a one-item iterable containing *obj*::
|
||
|
|
||
|
>>> obj = 1
|
||
|
>>> list(always_iterable(obj))
|
||
|
[1]
|
||
|
|
||
|
If *obj* is ``None``, return an empty iterable:
|
||
|
|
||
|
>>> obj = None
|
||
|
>>> list(always_iterable(None))
|
||
|
[]
|
||
|
|
||
|
By default, binary and text strings are not considered iterable::
|
||
|
|
||
|
>>> obj = 'foo'
|
||
|
>>> list(always_iterable(obj))
|
||
|
['foo']
|
||
|
|
||
|
If *base_type* is set, objects for which ``isinstance(obj, base_type)``
|
||
|
returns ``True`` won't be considered iterable.
|
||
|
|
||
|
>>> obj = {'a': 1}
|
||
|
>>> list(always_iterable(obj)) # Iterate over the dict's keys
|
||
|
['a']
|
||
|
>>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit
|
||
|
[{'a': 1}]
|
||
|
|
||
|
Set *base_type* to ``None`` to avoid any special handling and treat objects
|
||
|
Python considers iterable as iterable:
|
||
|
|
||
|
>>> obj = 'foo'
|
||
|
>>> list(always_iterable(obj, base_type=None))
|
||
|
['f', 'o', 'o']
|
||
|
"""
|
||
|
if obj is None:
|
||
|
return iter(())
|
||
|
|
||
|
if (base_type is not None) and isinstance(obj, base_type):
|
||
|
return iter((obj,))
|
||
|
|
||
|
try:
|
||
|
return iter(obj)
|
||
|
except TypeError:
|
||
|
return iter((obj,))
|