<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def join(self, column_label, other, other_label=None):
 """Creates a new table with the columns of self and other, containing rows for all values of a column that appear in both tables. Args: ``column_label`` (``str``):
 label of column in self that is used to join rows of ``other``. ``other``: Table object to join with self on matching values of ``column_label``. Kwargs: ``other_label`` (``str``):
 default None, assumes ``column_label``. Otherwise in ``other`` used to join rows. Returns: New table self joined with ``other`` by matching values in ``column_label`` and ``other_label``. If the resulting join is empty, returns None. a | b | c 9 | 1 | 3 3 | 2 | 4 3 | 2 | 5 1 | 10 | 6 a | d | e 9 | 1 | 3 1 | 2 | 4 1 | 2 | 5 1 | 10 | 6 a | b | c | d | e 1 | 10 | 6 | 2 | 4 1 | 10 | 6 | 2 | 5 1 | 10 | 6 | 10 | 6 9 | 1 | 3 | 1 | 3 a | b | c | d | e 1 | 10 | 6 | 2 | 4 1 | 10 | 6 | 2 | 5 1 | 10 | 6 | 10 | 6 9 | 1 | 3 | 1 | 3 a | b | c | a_2 | e 1 | 10 | 6 | 9 | 3 a | d | e 9 | 1 | 3 1 | 2 | 4 1 | 2 | 5 1 | 10 | 6 a | b | c 9 | 1 | 3 3 | 2 | 4 3 | 2 | 5 1 | 10 | 6 """

        if self.num_rows == 0 or other.num_rows == 0:
            return None
        if not other_label:
            other_label = column_label

        self_rows = self.index_by(column_label)
        other_rows = other.index_by(other_label)

        # Gather joined rows from self_rows that have join values in other_rows
        joined_rows = []
        for v, rows in self_rows.items():
            if v in other_rows:
                joined_rows += [row + o for row in rows for o in other_rows[v]]
        if not joined_rows:
            return None

        # Build joined table
        self_labels = list(self.labels)
        other_labels = [self._unused_label(s) for s in other.labels]
        other_labels_map = dict(zip(other.labels, other_labels))
        joined = type(self)(self_labels + other_labels).with_rows(joined_rows)

        # Copy formats from both tables
        joined._formats.update(self._formats)
        for label in other._formats:
            joined._formats[other_labels_map[label]] = other._formats[label]

        # Remove redundant column, but perhaps save its formatting
        del joined[other_labels_map[other_label]]
        if column_label not in self._formats and other_label in other._formats:
            joined._formats[column_label] = other._formats[other_label]

        return joined.move_to_start(column_label).sort(column_label)