Programm funktioniert nicht.

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
pywald
User
Beiträge: 45
Registriert: Mittwoch 6. Januar 2021, 15:51

Hallo,
Warum funktioniert dieses Programm nicht?
Der Code sollte eigentlich die Nachricht als erstes verschlüsseln und dann wieder entschlüsseln.
Der Code:

Code: Alles auswählen

import random
nachricht = "Hallo"
nachricht = list(nachricht)
nachricht_länge = len(nachricht) + 1
gerade = []
ungerade = []
for counter in range(0, nachricht_länge, 2):
    gerade.append(nachricht[counter])
nachricht_länge -= 2
for counter in range(1, nachricht_länge, 2):
   ungerade.append(nachricht[counter])
def gerade_funktion(nummer):
    return nummer % 2 == 0
Gerade_T_F = gerade_funktion(len(nachricht))
if Gerade_T_F == True:
    nachricht.append("x")
def tausch(gerade, ungerade):
    for index in range(0, int(len(nachricht)/2)):
        nachricht.append(gerade[index])
        nachricht.append(ungerade[index])
        return nachricht
print(tausch(gerade, ungerade))
Die Ausgabe:
['H', 'a', 'l', 'l', 'o', 'H', 'a']

Danke
pywald
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum hat Deine gerade-Funktion funktion im Namen?
Wenn man zur Nachrichtenlänge nicht erst 1 draufaddiert muß man später nicht 2 abziehen. Zumal das für eine gerade Anzahl an Buchstaben eh nicht funktioniert.

Da Strings auch Indizierung verstehen, verkürzt sich der erste Teil auf

Code: Alles auswählen

nachricht = "Hallo"
gerade = nachricht[::2]
ungerade = nachricht[1::2]
Was soll eigentlich bei der Variablen Gerade_T_F das T und das F bedeuten? Benutze keine Abkürzungen! Variablennamen werden komplett klein geschrieben. Explizit mit True vergleicht man nicht.

Dass da nachträglich die nachricht geändert wird, führt in tausch trotzdem zu einem Index-Error.
Wenn man Ganzzahl-Division benutzt, braucht man das Ergebnis nicht nachträglich wieder in ein int verwandeln.
`tausch` benutzt die globale Variable nachricht und ändert sie auch noch. Außerdem ist das `return` falsch eingerückt.

`nachricht` wird für `tausch` gar nicht gebraucht, weil eigentlich die Länge von `gerade` interessiert.

Code: Alles auswählen

def tausch(gerade, ungerade):
    if len(gerade) != len(ungerade):
        ungerade += "x"
    nachricht = []
    for index in range(0, len(gerade)):
        nachricht.append(gerade[index])
        nachricht.append(ungerade[index])
    return "".join(nachricht)
Statt einem Index benutzt man zip:

Code: Alles auswählen

def tausch(gerade, ungerade):
    if len(gerade) != len(ungerade):
        ungerade += "x"
    nachricht = []
    for g, u in zip(gerade, ungerade):
        nachricht.append(g)
        nachricht.append(u)
    return "".join(nachricht)
oder

Code: Alles auswählen

def tausch(gerade, ungerade):
    if len(gerade) != len(ungerade):
        ungerade += "x"
    return "".join(g+u for g, u in zip(gerade, ungerade))
Mit zip_longest hat man dann auch kein Problem mehr mit dem unnötigen `x`:

Code: Alles auswählen

from itertools import zip_longest
def tausch(gerade, ungerade):
    return "".join(g+u for g, u in zip_longest(gerade, ungerade, fillvalue=""))
Benutzeravatar
pywald
User
Beiträge: 45
Registriert: Mittwoch 6. Januar 2021, 15:51

Danke!
Eigentlich war es sowieso noch die erste Version des Programms.
Würdest du mir den ganzen Code aufführen?
Bin leider nicht richtig mitgekommen.
pywald
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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:

Code: Alles auswählen

    gerade = nachricht[0::2]
`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])
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
pywald
User
Beiträge: 45
Registriert: Mittwoch 6. Januar 2021, 15:51

Hallo,
Gerade_T_F soll gerade_True_False sein.
pywald
Benutzeravatar
pywald
User
Beiträge: 45
Registriert: Mittwoch 6. Januar 2021, 15:51

Vielen herzlichen Dank für die guten Antworten. Ihr habt mir sehr weitergeholfen.
pywald
Antworten