@pywald: Das ist sehr schwer zu lesen wie die Zeilen da so alle aneinander kleben und Programm und Funktionsdefinitionen vermischt sind.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).
`random` wird importiert aber nicht verwendet.
Die Funktion `tausch()` greift auf `nachricht` zu, sollte das aber nicht, denn alles was eine Funktion oder Methode ausser Konstanten benötigt wird als Argument(e) übergeben. Wenn das Hauptprogramm in einer Funktion steht, dann gibt es `nachricht` auch überhaupt.
Man sollte den gleichen Namen nicht an Werte mit verschiedenen Datentypen binden. Binde `nachricht` gleich an eine Liste und nicht erst an eine Zeichenkette.
`nachricht_laenge` sollte die Länge der Nachricht enthalten und nicht mal die Länge der Nachricht plus eins und mal die Länge der Nachricht minus eins. Das ist verwirrend, denn bei dem Namen erwartet der Leser die tatsächliche Länge der Nachricht. Dieses ±1 ist aber sowieso komisch bis falsch, denn schauen wir uns mal eine Nachricht mit gerader Anzahl von Zeichen an:
Code: Alles auswählen
In [412]: nachricht = list("XX")
...:
...: gerade = []
...: for i in range(0, len(nachricht) + 1, 2):
...: gerade.append(nachricht[i])
...:
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-412-9b8946ccba8a> in <module>
3 gerade = []
4 for i in range(0, len(nachricht) + 1, 2):
----> 5 gerade.append(nachricht[i])
6
IndexError: list index out of range
Die beiden Schleifen um die `gerade` und `ungerade` Listen zu erzeugen schreien auch förmich danach als „list comprehension“ geschrieben zu werden:
Code: Alles auswählen
gerade = [nachricht[i] for i in range(0, len(nachricht), 2)]
...
Aber weil das Listen sind und die die „slice“-Notation für den Indexzugriff beherrschen geht das noch einfacher:
`gerade_funktion()` ist kein guter Name. Für Prüffunktionen die einen Wahrheitswert zurückgeben verwendet man üblicherweise die Vorsilbe `ist_*()` oder `hat_*()` (englisch `is_*()`/`has_*()`).
Keine kryptichen abkürzungen in Namen. Was soll denn `Gerade_T_F` bedeuten?
Man muss diesen Zwischenwert auch nicht an einen Namen binden.
Man macht keine Vergleiche mit literalen Wahrheitswerten. Bei dem Vergleich kommt doch nur wieder ein Wahrheitswert bei heraus. Entweder der, den man sowieso schon hatte; dann kann man den auch gleich nehmen. Oder das Gegenteil davon; dafür gibt es ``not``.
Zwischenstand:
Code: Alles auswählen
#!/usr/bin/env python3
def ist_gerade(zahl):
return zahl % 2 == 0
def tausche_zeichen(nachricht, gerade, ungerade):
for i in range(0, len(nachricht) // 2):
nachricht.append(gerade[i])
nachricht.append(ungerade[i])
return nachricht
def main():
nachricht = list("Hallo")
gerade = nachricht[0::2]
ungerade = nachricht[1::2]
if ist_gerade(len(nachricht)):
nachricht.append("x")
print(tausche_zeichen(nachricht, gerade, ungerade))
if __name__ == "__main__":
main()
Natürlich immer noch fehlerhaft. Jetzt sag mal an welcher Stelle das Programm nicht mehr das macht was Du erwartest. Geh das mal Stück für Stück durch. Teste jede einzelne Funktion ob sie das macht was Du erwartest. Sehen die Werte vor und nach den Aufrufen so aus wie Du das erwartest? Was gibst Du rein, was bekommst Du heraus, und wie unterscheided sich das von dem erwarteten Werten? Wie sehen diese erwarteten Werte aus?
`tausch()` beziehungsweise `tausche_zeichen()` hat eine falsche API. Man übergibt nicht etwas das man in einer Funktion verändert, und dann zurück gibt. Entweder verändert eine Funktion etwas, oder sie hat einen Rückgabewert. Das was man verändert braucht man nicht zurückgeben, weil der Aufrufer das Objekt ja bereits hat, sonst hätte er es nicht übergeben können.
Verändern ist aber auch nicht gut. Und hier wohl auch total falsch. Sauberer und einfacher nachzuvollziehen ist es wenn Funktionen ”rein” sind, also keine Nebeneffekte haben, sondern einen neuen Wert zurückgeben.
Ich vermute mal das gesamte Programm wäre einfach mit folgenden Zeilen abgefühstückt (ungetestet):
Code: Alles auswählen
nachricht = "..."
if len(nachricht) % 2 != 0:
nachricht += " "
print(nachricht[0::2] + nachricht[1::2])