docs: def cached_generator(function):
      """Method decorator caching a generator's yielded items."""
      cache_variable = '_cached_' + function.__name__
      @wraps(function)
      def function_wrapper(obj, *args, **kwargs):
          # values are cached in a list stored in the object
          try:
              for item in getattr(obj, cache_variable):
                  yield item
          except AttributeError:
              setattr(obj, cache_variable, [])
              cache = getattr(obj, cache_variable)
              for item in function(obj, *args, **kwargs):
                  cache.append(item)
                  yield item
      return function_wrapper