Korrekt.
Mein Trick ist, daß ich mit der zip()-Funktion zunächst eine Liste von Tupeln baue, und jedes der Tupel-Elemente in der Liste enthält die Inhalte der korrespondierenden Zeilen. Also das Tupel mit dem Index 0 in der Liste enthält die Daten der ersten, das Tupel-Element mit dem Index 1 in der Liste die aus der zweiten Zeile, und so weiter. Dadurch kann ich ganz einfach über eine weitere List Comprehension die Längen der Strings in den Zeilen ermitteln und mit der max()-Funktion die größte Länge dort herausziehen, und mit dieser Länge baue ich dann einen Teil-Formatstring wie "{:<30s}" für einen linksbündig ausgerichteten String mit 30 Zeichen. Diese Teil-Formatstrings werden dann über die str.join()-Methode zum Gesamt-Formatstring zusammengefaßt.
Nun habe ich meine originalen Inhalte aber noch in der Variablen "content", die ebenfalls eine Liste von Listen ist und in jeder der enthaltenen Listen die eingelesenen Inhalte einer meiner Textdateien enthält -- also das, was ich bei '--serial' oder '-s' in einer Zeile ausgeben möchte. Und genau darauf wende ich dann ganz einfach meinen oben zusammengebauten Formatstring an und gebe das Resultat aus.
Na klar. Ich habe den ArgumentParser so konfiguriert, daß er sogenannte "positional arguments" entgegennehmen kann, sowas kennst Du vielleicht (hoffentlich) von etlichen Kommandozeilenprogrammen wie less(1), cat(1) oder grep(1). So kannt Du mein Programm im Prinzip mit so vielen Dateinamen aufrufen, wie Du möchtest, bei Dir zum Beispiel mit zwei: "./programm.py names.txt numbers.txt", aber "./programm.py names.txt numbers.txt numbers.txt names.txt" oder andere Dateien gehen natürlich auch. (Es gibt da eine Grenze, die Deine Kommandozeilenumgebung festlegt, aber die ist heutzutage recht groß und soll uns jetzt hier nicht weiter interessieren). Der Name "filenames" und der Parameter "nargs='+'" in "parser.add_argument()" sorgen dafür, daß die übergebenen Dateinamen von parser.parse_args() in einer Liste (hier: "args") abgelegt werden, die Dein Programm dann im Folgenden über das Attribut "args.filenames" lesen, und -- wie ich hier -- darüber iterieren kann. Wenn Du das Programm also mit "./programm.py names.txt numbers.txt" aufrufst, enthält args.filenames nach dem Aufruf von parse_args() die Liste "['names.txt', 'numbers.txt']" -- und wenn ich mit "for filename in args.filenames:" darüber iteriere... genau.
Naja, die "args.filenames" sind wie gerade erklärt die übergebenen Dateinamen, und "filename" enthält dann für jeden Durchlauf der for-Schleife einen der Dateinamen. Ich öffne dann die Datei mit einem sogenannten "Context Manager" (with open()") zum Lesen, lese die Datei komplett ein, splitte den gelesenen Inhalt zeilenweise ("ifh.read().splitlines()") und hänge die so gewonnene Liste von Zeilen an meine Liste "contents" an, so daß "contents" am Ende eine Liste enthält, bei der jedes Element wiederum eine Liste der Zeilen aus der angegebenen Textdatei ist.
Tipp: füg' doch mal' nach dem "corresponding_lines" jeweils ein "print(contents)" und ein "print(corresponding_lines)" ein... viel Spaß und Erfolg!