docs: def group_by(self, key_selector=identity,
                   element_selector=identity,
                   result_selector=lambda key, grouping: grouping):
          '''Groups the elements according to the value of a key extracted by a
          selector function.
  
          Note: This method has different behaviour to itertools.groupby in the
              Python standard library because it aggregates all items with the
              same key, rather than returning groups of consecutive items of the
              same key.
  
          Note: This method uses deferred execution, but consumption of a single
              result will lead to evaluation of the whole source sequence.
  
          Args:
              key_selector: An optional unary function used to extract a key from
                  each element in the source sequence. The default is the
                  identity function.
  
              element_selector: A optional unary function to map elements in the
                  source sequence to elements in a resulting Grouping. The
                  default is the identity function.
  
              result_selector: An optional binary function to create a result
                  from each group. The first positional argument is the key
                  identifying the group. The second argument is a Grouping object
                  containing the members of the group. The default is a function
                  which simply returns the Grouping.
  
          Returns:
              A Queryable sequence of elements of the where each element
              represents a group.  If the default result_selector is relied upon
              this is a Grouping object.
  
          Raises:
              ValueError: If the Queryable is closed().
              TypeError: If key_selector is not callable.
              TypeError: If element_selector is not callable.
              TypeError: If result_selector is not callable.
          '''
          if self.closed():
              raise ValueError("Attempt to call group_by() on a closed "
                               "Queryable.")
  
          if not is_callable(key_selector):
              raise TypeError("group_by() parameter key_selector={0} is not "
                              "callable".format(repr(key_selector)))
  
          if not is_callable(element_selector):
              raise TypeError("group_by() parameter element_selector={0} is not "
                              "callable".format(repr(element_selector)))
  
          if not is_callable(result_selector):
              raise TypeError("group_by() parameter result_selector={0} is not "
                              "callable".format(repr(result_selector)))
  
          return self._create(self._generate_group_by_result(key_selector,
                              element_selector, result_selector))