@isi.one: Das wichtigste wäre hier das Du `eval()` vergisst. Das verwendet man nicht, schon gar nicht um einfach nur eine eingegebene Zeichenkette in eine Zahl zu wandeln. `eval()` führt beliebige Python-Ausdrücke aus. Im schlimmsten Fall ist das eine Sicherheitslücke, weil da auch was eingegeben werden kann, was beispielsweise die Dateien vom Benutzer unter dem das Programm läuft, gelöscht werden. Aber auch was die Fehlerbehandlung angeht ist das ein Albtraum, weil bei beliebigen Ausdrücken natürlich auch beliebige Ausnahmen auftreten können. Wenn man die vorgesehene `float()`-Funktion verwendet, muss man sich nur mit einem `ValueError` beschäftigen, falls der Benutzer etwas eingibt, das nicht in eine Zahl umgewandelt werden kann.
Den Aufruf der Funktion sollte man davor schützen das er auch passiert wenn das Modul nicht als Programm ausgeführt, sondern nur importiert wird. Aus einem anderen Modul, beispielsweise um die Funktion wiederzuverwenden, oder automatisiert zu testen (Unit-Tests), oder in einer interaktiven Python-Shell, um die Funktion auszuprobieren, oder Fehler zu suchen. Es gibt auch Werkzeuge die Module importieren und sich darauf verlassen, dass dabei keine Seiteneffekte passieren, sondern nur Konstanten, Funktionen, und Klassen definiert werden. Zum Beispiel um den Code zu analysieren, oder Dokumentation aus dem Quelltext zu ziehen.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase). Funkionen (und Methoden) werden nicht nur komplett klein geschrieben, sondern üblicherweise auch nach der Tätigkeit benannt die sie durchführen, damit der Leser eine Idee hat, was da passiert, und um sie von eher passiven Werten unterscheiden zu können. `Taschenrechner` wäre also eher ein Name für eine Klasse und `taschenrechner` der Name für einen Wert der einen Taschenrechner als Objekt repräsentiert.
Hier würde ich einfach den traditionellen Namen für die Hauptfunktion eines Programms verwenden: `main()`.
Man nummeriert keine Namen. Das ist hier in gewisser Weise ein Sonderfall, weil man zwei mehr oder weniger gleichberechtigte Werte als Operanden hat, aber auch hier würde ich nicht einfach eine Nummer anhängen. Ich würde das entweder als Zahlworte in den Namen aufnehmen, oder als relative Positionsangabe zum Operator, also `erster_operand` und `zweiter_operand` oder `linker_operand` und `rechter_operand`. So wie man das in natürlicher Sprache ausdrücken würde.
`operator` kann nur einen der vier Werte annehmen, auf die dort mit ``if`` getestet wird. Das ist also ein Fall für ``elif``-Anweisungen nach dem ersten ``if``.
Und dann hat man ein ``if``-Konstrukt das mit einem ``elif`` endet. An der Stelle sollte man sich immer Fragen ob man den ``else``-Fall einfach so ignorieren sollte. In diesem Fall würde das bedeuten, dass der Benutzer einen falschen Operator eingegeben hat. Darauf könnte/sollte man ihn vielleicht hinweisen.
Zwischenstand (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python3
def main():
#
# TODO Fehlerbehandlung bei den Eingaben.
#
erster_operand = float(input("erste Zahl eingeben: "))
operator = input("wähle (+), (-), (*), (/): ")
zweiter_operand = float(input("zweite Zahl eingeben: "))
#
# TODO Test auf `operator` durch ein Wörterbuch ersetzen, dass die
# Operatorsymbole auf die entsprechenden Funktionen aus dem `operator`-Modul
# abbildet.
#
# TODO Nicht "Ergebnis =" in jedem Zweig wiederholen.
#
if operator == "+":
print("Ergebnis =", erster_operand + zweiter_operand)
elif operator == "-":
print("Ergebnis =", erster_operand - zweiter_operand)
elif operator == "*":
print("Ergebnis =", erster_operand * zweiter_operand)
elif operator == "/":
#
# TODO Fehlerbehandlung wenn der zweite Operand 0 ist.
#
print("Ergebnis =", erster_operand / zweiter_operand)
else:
print("Unbekannter Operator:", repr(operator))
if __name__ == "__main__":
main()
Da sind noch ein paar TODOs als Kommentare drin. Bei Eingaben von Benutzern sollte man immer mit allem Möglichen rechnen. Von Tippfehlern, über ehrliche Verständnisfehler/Missverständnisse, beispielsweise das einer hier denkt man müsse die Klammern bei den Operatoren mit eingeben, oder das Dezimalbrüche mit dem im deutschen üblichen Dezimalkomma eingegeben werden können; bis zu Benutzer die einfach mal die Grenzen ausloten wollen mit welchen Eingaben man das wohl zum Absturz bringen könnte.
Da zweimal eine Zahl eingebeben werden muss, sollte mindestens das in einer eigenen Funktion stehen die zweimal aufgerufen wird, statt den Code dafür zu wiederholen.
Im `operator`-Modul in der Standardbibliothek gibt es eine Funktion für jeden Operator den Python kennt. Statt die Auswahl einer Rechenoperation aufgrund einer eingegebenen Zeichenkette durch ``if`` mit Code zu treffen, könnte man das über eine Datenstruktur lösen, welche die Symbole auf entsprechende Funktionen abbildet.
Damit wird man dann auch die Wiederholung von der Zeichenkette "Ergebnis =" in jedem Zweig los. Code- und Datenwiederholungen vermeidet man als Programmierer. Wenn man mal Änderungen vornehmen will oder muss, dann muss man bei Kopien von Code und/oder Daten immer daran denken das an allen Stellen zu ändern, und auch gleich, oder zumindest gleichwertig tun. Das ist unnötige Arbeit und eine Fehlerquelle die man vermeiden kann.
Beim Teilen durch 0 kann eine Ausnahme auftreten die man behandeln sollte.