docs: def get_words(s, splitter_regex=rex.word_sep_except_external_appostrophe,
                preprocessor=strip_HTML, postprocessor=strip_edge_punc, min_len=None,
                max_len=None, blacklist=None, whitelist=None, lower=False,
                filter_fun=None, str_type=str):
      r"""Segment words (tokens), returning a list of all tokens
  
      Does not return any separating whitespace or punctuation marks.
      Attempts to return external apostrophes at the end of words.
      Comparable to `nltk.word_toeknize`.
  
      Arguments:
        splitter_regex (str or re): compiled or uncompiled regular expression
          Applied to the input string using `re.split()`
        preprocessor (function): defaults to a function that strips out all HTML tags
        postprocessor (function): a function to apply to each token before return it as an element in the word list
          Applied using the `map()` builtin
        min_len (int): delete all words shorter than this number of characters
        max_len (int): delete all words longer than this number of characters
        blacklist and whitelist (list of str): words to delete or preserve
        lower (bool): whether to convert all words to lowercase
        str_type (type): typically `str` or `unicode`, any type constructor that should can be applied
          to all words before returning the list
  
      Returns:
        list of str: list of tokens
  
      >>> get_words('He said, "She called me \'Hoss\'!". I didn\'t hear.')
      ['He', 'said', 'She', 'called', 'me', 'Hoss', 'I', "didn't", 'hear']
      >>> get_words('The foxes\' oh-so-tiny den was 2empty!')
      ['The', 'foxes', 'oh-so-tiny', 'den', 'was', '2empty']
      """
      # TODO: Get rid of `lower` kwarg (and make sure code that uses it doesn't break)
      #       That and other simple postprocessors can be done outside of get_words
      postprocessor = postprocessor or str_type
      preprocessor = preprocessor or str_type
      if min_len is None:
          min_len = get_words.min_len
      if max_len is None:
          max_len = get_words.max_len
      blacklist = blacklist or get_words.blacklist
      whitelist = whitelist or get_words.whitelist
      filter_fun = filter_fun or get_words.filter_fun
      lower = lower or get_words.lower
      try:
          s = open(s, 'r')
      except (IOError, FileNotFoundError):
          pass
      try:
          s = s.read()
      except (IOError, AttributeError, TypeError):
          pass
      if not isinstance(s, basestring):
          try:
              # flatten the list of lists of words from each obj (file or string)
              return [word for obj in s for word in get_words(obj)]
          except (IOError, IndexError, ValueError, AttributeError, TypeError):
              pass
      try:
          s = preprocessor(s)
      except (IndexError, ValueError, AttributeError, TypeError):
          pass
      if isinstance(splitter_regex, basestring):
          splitter_regex = re.compile(splitter_regex)
      s = list(map(postprocessor, splitter_regex.split(s)))
      s = list(map(str_type, s))
      if not filter_fun:
          return s
      return [word for word in s if
              filter_fun(word, min_len=min_len, max_len=max_len,
                         blacklist=blacklist, whitelist=whitelist, lower=lower)]