Da ich in deinem Code gesehen hatte, dass du bereits das Spaltenmaximum ermittelst, hier dann doch mal der Weg, den ich einschlagen würde:
Code: Alles auswählen
>>> rows
[['foo', 'longfoo', 'longestfoo'], ['a lot of spam', 'nomalspam', 'spam']]
>>> [max(len(item) for item in column_items) for column_items in zip(*rows)]
[13, 9, 10]
`zip()` vereint sozusagen die `i`-ten Elemente von "Auflistungen" - genauer gesagt: von allem, über das iteriert werden kann. Mal zum besseren Nachvollziehen:
Code: Alles auswählen
>>> zip([1,2,3], [1,3,6])
[(1, 1), (2, 3), (3, 6)]
Aber genau so gut auch:
Code: Alles auswählen
>>> zip("abc", "acf")
[('a', 'a'), ('b', 'c'), ('c', 'f')]
`zip()` arbeitet allerdings etwas anders als `.join()`. Während `.join()` *ein* Objekt erwartet, über welches es iteriert, erwartet `zip()` eine *beliebige* Anzahl von Argumenten, d.h. sozusagen: `[rows[0], rows[1], rows[2], ...]`, nur eben als `zip(rows[0], rows[1], rows[2], ...)`. Um dies zu bewerkstelligen, wird der Stern benötigt. Details zu dieser Technik sind übrigens in der Doku im Abschnitt
Unpacking Argument Lists beschrieben.
Und im linken Teil des o.g. Ausdrucks - also alles, was von `max(...)` umschlossen wird - nehme ich mir jeweils *eine* Spalte aus dem Ergebnis von `zip(*rows)` und durchlaufe deren Elemente, um das jeweilige Maximum zu ermitteln. `column_items` beinhaltet also nicht eine Liste aller Spalten, sondern es bekommt bei jedem Durchlauf einen neuen Wert zugewiesen, der die Elemente der *aktuellen* Spalte repräsentiert. Das kann man anfangs IMHO leicht durcheinander bringen.
So, und zu guter Letzt soll die Spaltenlänge ja wie gesagt dynamisch in die Formatierungsangaben eingefügt werden. Dazu nutzt man verschachteltes String-Formatting - also ein Formatierungsausdruck, der seinerseits aus einem anderen Formatierungsausdruck ermittelt wird. Für das Beispiel aus dem vorherigen Beitrag ginge das so:
Code: Alles auswählen
>>> '{:{}}'.format('foo', 20)
'foo '
>>> '{:{}}'.format(3 * 'foo', 20)
'foofoofoo '
Die Angabe hinter dem Doppelpunkt wird also aus einer "externen" Quelle eingefügt, quasi so als wenn sie ein Wort oder ähnliches wäre.
Will man hingegen nur die Formatierungsangabe ermitteln, aber noch keine Zeichenkette einsetzen, dann muss man die äußeren Klammern escapen, d.h. vor einer Interpretierung seitens der Formatting-Engine schützen:
Code: Alles auswählen
>>> '{:{}}'.format(20) # falsch
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
>>> '{{:{}}}'.format(20) # richtig
'{:20}'
Die zu schützenden Klammern (hier: das äußere Klammernpaar) werden also doppelt hingeschrieben.
Und jetzt möchtest du vielleicht mal probieren, wie du in einer Schleife deine eigenen Maximalwerte benutzen kannst. Als kleinen Hinweis möchte ich noch erwähnen, dass du zur Ermittlung der Maximalwerte in Spalten, aber beim späteren Einsetzen besser in Zeilen denken solltest. Ich würde Ermitteln und Einsetzen also voneinander trennen.