Programm Wiederholen

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
Baronheart
User
Beiträge: 4
Registriert: Montag 7. August 2023, 18:54

Guten Abend,
ich entschuldige mich jetzt schonmal für diese dumme Frage, jedoch bin ich noch ein blutiger Anfänger und ich habe auf meine Frage keine plausible Antwort gefunden.
Ich habe ein einfaches Taschenrechner Programm geschrieben (Bei Verbesserungsvorschlägen meldet euch gerne). Nun das Problem, ich würde gerne am ende der Rechnung jedesmal fragen ob noch eine Aufgabe ausgerechnet werden soll, dies wird auch einmal gemacht, jedoch nur einmal. Danach geht der Taschenrechner in eine endlos schleife und es wird nicht mehr nachgefragt.

Code: Alles auswählen

print("Taschenrechner")
zahl1 = eval(input("Bitte geben Sie die erste Zahl ein :"))
zahl2 = eval(input("Bitte geben Sie die zweite Zahl ein :"))
Zeichen = input("Bitte geben Sie die den Operator ein :")
if Zeichen == "+":
    print("Das Ergebnis ist:" ,zahl1+zahl2)
elif Zeichen == "-":
    print("Das ergebnis ist:" ,zahl1-zahl2)
elif Zeichen == "*":
    print("Das Ergebnis ist:" ,zahl1*zahl2)
elif Zeichen == "/":
    print("Das Ergebnis ist: " ,zahl1/zahl2)
else:
    print("falsches Zeichen")
wiederholung = input("Moechten Sie noch eine Rechnung? Ja/Nein: ")
while wiederholung == "Ja" or  wiederholung == "ja":
    zahl1 = eval(input("Bitte geben Sie die erste Zahl ein :"))
    zahl2 = eval(input("Bitte geben Sie die zweite Zahl ein :"))
    Zeichen = input("Bitte geben Sie die den Operator ein :")
    if Zeichen == "+":
         print("Das Ergebnis ist:" ,zahl1+zahl2)
    elif Zeichen == "-":
        print("Das ergebnis ist:" ,zahl1-zahl2)
    elif Zeichen == "*":
     print("Das Ergebnis ist:" ,zahl1*zahl2)
    elif Zeichen == "/":
        print("Das Ergebnis ist: " ,zahl1/zahl2)
    else:
        print("falsches Zeichen")

LG und einen schönen Abend :)
Benutzeravatar
noisefloor
User
Beiträge: 4194
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

du musst nur die Schleife anders setzen.

Beispiel:

Code: Alles auswählen

>>> while True:
...     print('Hallo Schleife!')
...     answer = input('Nochmal (ja für nochmal, alles andere für Ende)? ')
...     if not answer.lower()=='ja':
...         break
...
Zum Code gibt's einiges zu sagen, leider fehlt mir gerade die Zeit. Jedenfalls _nie_ eval benutzen, wenn man nicht ganz ganz genau weiß, was man tut. Das kann ein massives Sicherheitsrisiko sein.

Gruß, noisefloor
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Und hier ist `eval()` auch überhaupt nicht sinnvoll, denn für das umwandeln einer Zeichenkette in eine Zahl gibt es die `float()`-Funktion.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

`eval` darf in einem sauberen Programm nicht vorkommen, zum Umwandeln von Zahlen benutzt man `float`. Variablennamen werden generell klein geschrieben, Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht mal 1, mal 4 und mal 5.
Kopierten Code sollte man beim Programmieren vermeiden. Du hast den eigentlichen Taschenrechner zweimal im Programm. Das läßt sich vermeiden, indem man die Schleife umstellt.
Du fragst einmal für der while-Schleife das `wiederholung` ab, und änderst es innerhalb der Schleife nie. Das bedeutet, die Schleife läuft entweder nie oder unendlich oft durch. Die Voraussetzungen für Schleifenbedingung muß sich innerhalb der Schleife ändern, sonst macht man etwas falsch (außer bei gewollten Endlosschleifen;-)

Ein typischer Schleifentyp ist der, bei dem die Bedingung am Ende abgefragt wird; dafür gibt es in Python kein extra Konstrukt, sondern man muß sich mit einer Endloschleife und break behelfen:

Code: Alles auswählen

print("Taschenrechner")
while True:
    zahl1 = float(input("Bitte geben Sie die erste Zahl ein :"))
    zahl2 = float(input("Bitte geben Sie die zweite Zahl ein :"))
    rechenoperation = input("Bitte geben Sie die den Operator ein :")
    if rechenoperation == "+":
        print("Das Ergebnis ist:", zahl1 + zahl2)
    elif rechenoperation == "-":
        print("Das ergebnis ist:", zahl1 - zahl2)
    elif rechenoperation == "*":
        print("Das Ergebnis ist:", zahl1 * zahl2)
    elif rechenoperation == "/":
        print("Das Ergebnis ist: ", zahl1 / zahl2)
    else:
        print("falsches Zeichen")
    wiederholung = input("Möchten Sie noch eine Rechnung? Ja/Nein: ")
    if wiederholung.lower() != "ja":
        break
Benutzeravatar
snafu
User
Beiträge: 6870
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Sirius3 hat geschrieben: Mittwoch 16. August 2023, 08:13 `eval` darf in einem sauberen Programm nicht vorkommen, zum Umwandeln von Zahlen benutzt man `float`.
Schon verständlich bezüglich float(). Aber bei solchen pauschalen Aussagen muss man sich fragen, warum eval() dann existiert. Ich denke schon, dass es seinen Zweck hat. Nur wird dieser insbesondere von Anfängern oft nicht sinnvoll genutzt.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dafuer muss es keine gute Begruendung geben, weil Python ein Interpreter ist, hat man's halt mal eingebaut - und die Konsequenzen nicht ueberissen. Aber wenn es einmal drin ist, bekommt man es auch nicht mehr raus. Und mir faellt auch wirklich kein echter Zweck ein.
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@snafu: Echt jetzt?

Das muss man sich nicht fragen. Nur weil etwas existiert, muss man das nicht benutzen, und Sachen die existieren, können Sachen sein die man nicht benutzen sollte. So ganz pauschal. Globale Variablen existieren. ``global`` existiert. `os.system()` existiert. Man kann SQL als Zeichenkette mit Werten zusammenbasteln und das an Datenbanken verfüttern. Man kann alles in Klassen stecken und jede Klasse einzeln in ein Modul. Hat alles ganz pauschal nichts in sauberen Programmen verloren.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
DeaD_EyE
User
Beiträge: 1240
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

eval wird sogar sinnvoll eingesetzt und es ist sogar schneller.
Wenn man weiß, was man macht, dann darf man auch eval nutzen.

Code: Alles auswählen

[andre@andre-Fujitsu-i5 jinja]$ grep -R "eval("
tests/test_nativetypes.py:def test_no_intermediate_eval(env):
src/jinja2/nativetypes.py:        return literal_eval(
src/jinja2/nodes.py:    representation (objects where ``eval(repr(x)) == x`` is true).
src/jinja2/lexer.py:                value = literal_eval(value_str.replace("_", ""))
Es gibt sicherlich noch andere, sehr prominente Beispiele. Ich finde das immer so witzig, dass einerseits immer herum theoretisiert wird, aber anderseits Bibliotheken genutzt werden, die komplett gegensätzlich sind und diese Tricks anwenden.

Wusstet ihr, dass jinja2 die Templates mit eval befüllt?
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich finde es ironisch, das du zum vermeintlichen Beleg, dass eval ja durchaus benutzt wird, einen test-case case mit literal_eval anführst, das >90% aller Nutzungen von eval ablöst. Weil es Python literale übersetzt, ohne weitere Seiteneffekte. Was die Nutzung von eval auch hier und anderswo unnötig macht.

Das jinja das macht, ist kein Beleg dafür, das es gut ist. Sondern eher dafür, dass es ähnlich zu log4j ein Problem darstellt, das nur darauf wartet, ausgenutzt zu werden.
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DeaD_EyE: Dir ist schon klar das Deine Shell-Session da kein einziges `eval()` zeigt das da ausgeführt wird‽

Jinja benutzt kein `eval()` sondern `exec()` und Jinja ist als Template-Bibliothek auch ein besonderer Fall.

Und natürlich gibt es auch Gründe ``global`` zu verwenden. Trotzdem darf man NIEMALS ``global`` verwenden, in einem sauberen Programm.

Das Bibliotheken die komplett grundsätzlich sind, solche Tricks anwenden ist ja auch okay. Solche Bibliotheken schreibt man ja auch nicht selbst.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Baronheart
User
Beiträge: 4
Registriert: Montag 7. August 2023, 18:54

Vielen Dank für eure Hilfe, genauso sollte das Programm laufen. Jetzt kann ich die Methode lernen 🙂

Eine wichtige Sache für meinen Lerneffekt. Was ist am 'eval' Befehl ein Sicherheitdrisiko?
Ich hatte es so gelernt das der eval Befehl die Eingabe automatisch richtig einsortiert in Zahl Buchstabe oder Zeichen. Für mich wirkte es wie eine sinnvolle Methode.


Lg
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn Du das so gelernt hast, dann hast Du noch nie Buchstaben bei eval eingegeben. Laß Dich überraschen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

eval erlaubt prinzipiell das ausführen beliebigen Codes. Wen du also einen Benutzer Eingaben mache lässt, kann der damit im Zweifel so nette Dinge wie deine ganze Platte löschen anstellen. Etc pp.
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Davon mal abgesehen kann man auch Fehleingaben nicht wirklich sinnvoll behandeln. Bei `float()` kann es einen `ValueError` geben auf den man reagieren kann. Bei `eval()` kann so gut wie alles passieren. Angefangen mit Syntaxfehlern, die man sonst eigentlich *nie* behandeln muss, weil das eigentlich immer ein Problem ist das man im eigenen Code lösen sollte.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
noisefloor
User
Beiträge: 4194
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

zum Thema löschen via eval: https://realpython.com/python-eval-func ... es-of-eval zeigt, wie an zumindest des aktuelle Homeverzeichnis ohne weitere Rückfragen via eval löscht.

Unter https://nedbatchelder.com/blog/201206/e ... erous.html gibt es weitere Beispiele.

Wie schon gesagt wurde: einfach nicht benutzen. Was nicht heißt, dass es nutzlos ist.

Gruß, noisefloor
Baronheart
User
Beiträge: 4
Registriert: Montag 7. August 2023, 18:54

Vielen Dank. Dann werde ich demnächst float für Zahlen benutzen.

Ich hätte noch eine Frage (off-Topic), mein Programm zeigt sobald ich ein ä, ü, ö verwende eine Fehlermeldung an. Ist dies eine Einstellungssache oder kann man das irgendwie umgehen?
Sirius3
User
Beiträge: 18273
Registriert: Sonntag 21. Oktober 2012, 17:20

Das liegt wahrscheinlich daran, dass Dein Editor falsch eingestellt ist. Du mußt die Datei UTF8-kodiert speichern.
Antworten