docs: def join(self, right_table, on=None, right_prefix='R.', outer=False):
          """
          Inner-joins another DataTable to this one using `on` (iterable of join
          keys). If two tables share columns other than the join keys, appends
          right_prefix to the right table's column name. If `on` is not
          provided, performs a 'natural join' using all columns of the same name.
          """
          if on is None:  # if no 'on', perform natural join
              on = list(set(self.fields).intersection(set(right_table.fields)))
          if isinstance(on, basestring):
              on = [on]
              
          def get_join_key(row):
              return tuple(row[header] for header in on)
          
          keymap = defaultdict(list)
          for right_row in right_table:
              keymap[get_join_key(right_row)].append(right_row)
          new_table = []
          for left_row in self:
              left_key = get_join_key(left_row)
              if left_key in keymap:
                  left_dict = dict(left_row.items())
                  for right_row in keymap[left_key]:
                      left_dict_copy = left_dict.copy()
                      for field, val in right_row.items():
                          if field in on:
                              continue
                          elif field in left_row:
                              left_dict_copy[right_prefix + field] = val
                          else:
                              left_dict_copy[field] = val
                      new_table.append(left_dict_copy)
              elif outer:
                      left_dict_copy = dict(left_row.items()).copy()
                      for field in right_table.fields:
                          if field in on:
                              continue
                          elif field in left_row:
                              left_dict_copy[right_prefix + field] = None
                          else:
                              left_dict_copy[field] = None
                      new_table.append(left_dict_copy)
  
          return DataTable(new_table)