docs: def get_by_cols(self, cols, direction=1):
          """Return the first or last row that satisfies the given col value constraints,
          or None if no row contains the given value.
  
          Parameters
          ----------
          cols: :obj:'dict'
              Dictionary of col values for a specific row.
          direction: int, optional
              Either 1 or -1. 1 means find the first row, -1 means find the last row.
  
          Returns
          -------
          :obj:`dict`
              A dictionary mapping keys (header strings) to values, which
              represents a row of the table. This row contains the given value in
              the specified column.
          """
          if direction == 1:
              iterator = range(self.num_rows)
          elif direction == -1:
              iterator = range(self.num_rows-1, -1, -1)
          else:
              raise ValueError("Direction can only be 1 (first) or -1 (last). Got: {0}".format(direction))
  
          for i in iterator:
              row = self._table[i+1]
  
              all_sat = True
              for key, val in cols.items():
                  if row[key] != val:
                      all_sat = False
                      break
  
              if all_sat:
                  return row.copy()
  
          return None