Drawing a table in Python3 I have created a module to draw text tables. The relevant parts are below and here's the full code for txtable).

class Row(Txtable):
    [...]
    def format(self, col_widths):
        """Return the row as formatted string.
        """

        columns = []
        for x, column in enumerate(self.columns):
            # skip empty rows
            if 0 == len(str(column)):
                columns.append((" " * col_widths[x]))
                continue
            columns.append(self.format_cell(x, col_widths[x]))
        return str(" " * self.col_spacing).join(columns)


class Table(Txtable):
    [...]
    def add_rows(self, rows):
        """Add multiple rows.
        """

        for columns in rows:
            self.add_row(columns)

    [...]
    def render(self):
        """Return the table as a string.
        """

        # render cells and measure column widths
        for y, row in enumerate(self.rows):
            for x, column in enumerate(row.columns):
                fmt_column = row.format_cell(x)
                width = len(fmt_column)
                try:
                    if self.col_widths[x] &lt; width:
                        self.col_widths[x] = width
                except IndexError:
                    self.col_widths.append(width)
        # render the table with proper spacing
        output = ""
        lmarg = (" " * self.margin)
        for row in self.rows:
            [...do rest of the rendering...]


I'd like to know about ways I could optimize this please. I see I could calculate the maximum column widths in Table.add_rows() instead of Table.render(), but I'd like to keep the possibility to modify the rows before rendering the final output.

How could I cut back on the looping? Is there a better way to output tabular data?
The nested loop under # render cells and measure column widths computes maximum cell width of each column. Using itertools.zip_longest to turn columns into rows lets you use max on them:

cell_widths = [[len(row.format_cell(x)) for x in range(len(row.columns))]
                for row in self.rows]
col_widths = list(map(max, itertools.zip_longest(*cell_widths, fillvalue=0)))