| Viewing file:  _itertools.py (2.02 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
from itertools import filterfalse
 
 def unique_everseen(iterable, key=None):
 "List unique elements, preserving order. Remember all elements ever seen."
 # unique_everseen('AAAABBBCCDAABBB') --> A B C D
 # unique_everseen('ABBCcAD', str.lower) --> A B C D
 seen = set()
 seen_add = seen.add
 if key is None:
 for element in filterfalse(seen.__contains__, iterable):
 seen_add(element)
 yield element
 else:
 for element in iterable:
 k = key(element)
 if k not in seen:
 seen_add(k)
 yield element
 
 
 # copied from more_itertools 8.8
 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,))
 
 |