Ja oder nein Abfrage

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
Sdlogni
User
Beiträge: 2
Registriert: Sonntag 29. Januar 2017, 15:29

Hallo zusammen
Ich beschäftige mich ganz neu mit Python und Programmieren ganz allgemein.

bei meiner ersten Übung stosse ich an Grenzen:

hier der code:

Code: Alles auswählen

print("Benzinrechner")

eingabeKm = input("Anzahl gefahrene km: ")
km = eval(eingabeKm)
if km < 50:
    print("fahre noch ein paar KM weiter, bis du den Verbrauch ausrechnen lassen willst")   
    eingabeWeitereFrage = input("Haben Sie noch weitere Fragen? (Y/N:) ") 
    WeitereFrage = eval(eingabeWeitereFrage)
    if WeitereFrage == N:
        print("dann machen wir hier Schluss")
else:
    eingabeLiter = input("getankte Menge Benzin in Liter: ")
    Liter = eval(eingabeLiter)
    print("der durchschnittliche Verbrauch liegt bei", Liter * 100 / km , "Liter pro 100km")
wie muss ich es anstellen, dass ich nach der Engabe bei weitere Frage mit Y oder N weiter komme?
Irgendwie muss ich N ode Y als Variable deklarieren, aber wie und wo?

Danke für euren Tip.
Gruss

Nik
Zuletzt geändert von Anonymous am Sonntag 29. Januar 2017, 16:23, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sdlogni: was willst Du denn, was passiert, wenn jemand »Y« oder »N« eintippt?

Vergiß, daß es »eval« gibt. Wenn Du einen String in eine Zahl umwandeln willst, nimm »float« oder »int«. Bei der Frage nach "Y/N" hast Du schon einen String, den Du direkt vergleichen kannst »WeitereFrage == "N"«.
BlackJack

@Sdlogni: Als erstes solltest Du `eval()` nicht verwenden. Um eine Eingabe in eine ganze Zahl umzuwandeln gibt es die `int()`-Funktion und für Gleitkommazahlen die `float()`-Funktion. Und wenn man die Eingabe als Zeichenkette haben möchte dann macht man gar nichts damit, denn `input()` liefert ja bereits eine Zeichenkette.

`eval()` führt jeden beliebigen Python-Ausdruck aus. Der Benutzer kann da sonst was eingeben. Auch Eingaben die alle Deine Dateien löschen. Selbst wenn der Benutzer nichts bösartiges plant, ist es schwer *sicher* mit `eval()` zu operieren, weil bei beliebigen Ausdrücken auch beliebige Fehler/Ausnahmen auftreten können. Das abzusichern und sinnvoll zu behandeln ist nicht leicht und zudem halt auch völlig überflüssig wenn man einfach nur eine Zahl haben möchte.

Du könntest `N` natürlich vorher definieren, aber warum? An der Stelle kannst Du den Wert den Du an `N` binden würdest auch einfach direkt angeben.

Lesetipp: Style Guide for Python Code.
Axel-Erfurt
User
Beiträge: 20
Registriert: Mittwoch 2. Oktober 2013, 22:15

python 2

Code: Alles auswählen

print("Benzinrechner")

eingabeKm = raw_input("Anzahl gefahrene km: ")
km = str(eingabeKm)
if int(km) < 50:
    print("fahre noch ein paar KM weiter, bis du den Verbrauch ausrechnen lassen willst")
    WeitereFrage = raw_input("Haben Sie noch weitere Fragen? (y/n:)")
    if str(WeitereFrage) == "n":
        print("dann machen wir hier Schluss")
    else:
        print("dann machen wir hier weiter") # was auch immer du dann noch fragen willst
else:
    eingabeLiter = raw_input("getankte Menge Benzin in Liter: ")
    Liter = float(eingabeLiter)
    print("der durchschnittliche Verbrauch liegt bei " + str(Liter * 100 / int(km)) + " Liter pro 100 km")
python3

Code: Alles auswählen

print("Benzinrechner")

eingabeKm = input("Anzahl gefahrene km: ")
km = str(eingabeKm)
if int(km) < 50:
    print("fahre noch ein paar KM weiter, bis du den Verbrauch ausrechnen lassen willst")
    WeitereFrage = input("Haben Sie noch weitere Fragen? (y/n:)")
    if str(WeitereFrage) == "n":
        print("dann machen wir hier Schluss")
    else:
        print("dann machen wir hier weiter") # was auch immer du dann noch fragen willst
else:
    eingabeLiter = input("getankte Menge Benzin in Liter: ")
    Liter = float(eingabeLiter)
    print("der durchschnittliche Verbrauch liegt bei " + str(Liter * 100 / int(km)) + " Liter pro 100 km")
 
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Axel-Erfurt: `raw_input` bzw. `input` liefern bereits Strings, der Aufruf von `str` ist also überflüssig. Es macht auch keinen Sinn, jedesmal, wenn man eine Zahl braucht, `km` wieder umzuwandeln. Kilometer sind von Natur aus Zahlen, dann sollte man sie auch gleich so speichern. Statt Strings mit + zusammenzustückeln, kann man wie Sdlogni mehrere Parameter an `print` übergeben, oder man benutzt `.format`.
Sdlogni
User
Beiträge: 2
Registriert: Sonntag 29. Januar 2017, 15:29

Danke für die raschen Feedbacks.

@Sirius3: es wäre schon toll, wenn bei ja oder auch bei nein ein weiterer Text angezeigt würde.
Das Eval habe ich heute Nachmittag irgendo aufgeschnapt.

Werde demnach versuchen, das ganze Konstrukt ohne diese Funktion aufzubauen.

@Axel Erfurt: ich werde Deine Vorschläge anschauen und versuchen, diese zu verstehen.

Werde mich bestimmt wieder melden, sei es bei Erfolg oder auch Misserfolg
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Sdlogni hat geschrieben:Das Eval habe ich heute Nachmittag irgendo aufgeschnapt.
Das klingt für einen erfahrenen Python-Entwickler jetzt so ähnlich wie: "Heute habe ich was von Ebola gehört und es mir sofort zugelegt."
Axel-Erfurt
User
Beiträge: 20
Registriert: Mittwoch 2. Oktober 2013, 22:15

hier mal als GUI Version

Code: Alles auswählen

#!/usr/bin/python
# -- coding: utf-8 --
import Tkinter as tk
import tkSimpleDialog, tkMessageBox

def ergebnis(self):
    label_4.config(text="")
    var_1 = len(entry_1.get())
    var_2 = len(entry_2.get())
    if  var_1 > 0 and var_2 > 0:
        km = float(entry_1.get().replace(",", "."))
        liter = float(entry_2.get().replace(",", "."))
        if km > 50:
            ausrechnen(km, liter)
        else:
            result = tkMessageBox.askyesno("Frage", "Fahren Sie noch ein paar km weiter, bis Sie den Verbrauch ausrechnen lassen!\n\nHaben Sie noch weitere Fragen?")
            if result == True:
                tkMessageBox.showinfo("Info", "Dann machen wir hier weiter")
                weiter()
            else:
                tkMessageBox.showinfo("Info", "Dann machen wir hier Schluss")
                quit()
    else:
        label_4.config(text="Eintrag fehlt!")
        label_4.configure(fg="red")

def nextfield(self):
    entry_2.focus()
    entry_2.select_range(0, tk.END)

def ausrechnen(km, liter):
    verbrauch =  round(liter * 100 / km, 2)
    result = ('{0} {1}'.format(verbrauch , "Liter pro 100 km"))
    label_4.config(text=result)
    if verbrauch > 6:
        label_4.configure(fg="red")
    else:
        label_4.configure(fg="green")

def weiter():
    tkMessageBox.showinfo("Info", "funktioniert!") # kann dann weg wenn code
    # code für weiter hier

root = tk.Tk()
root.title("Benzinverbrauch")
root.resizable(width=False, height=False)
root.geometry("260x130")

label_1 = tk.Label(root, text="gefahrene km").pack()

entry_1 = tk.Entry(root, width=10, justify="center")
entry_1.pack()
entry_1.bind("<Return>", nextfield)

label_2 = tk.Label(root, text="getankte Liter").pack()

entry_2 = tk.Entry(root, width=10, justify="center")
entry_2.pack()
entry_2.bind("<Return>", ergebnis)

label_3 = tk.Label(root, text="Verbrauch:").pack()

label_4 = tk.Label(root, text="", font=('', 13, "bold"))
label_4.pack()

entry_1.insert(0, "112,7")
entry_2.insert(0, "6,5")
entry_1.focus()
entry_1.select_range(0, tk.END)
root.mainloop()
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Axel-Erfurt: Variablennamen sollten aussagekräftig sein. Was hast Du Dir dabei gedacht die Länge eines Strings `var_1` zu nennen? `result` oder meintewegen `result_label` ist doch viel lesbarer als `label_4`. Weißt Du welchen Wert die ganzen anderen `label_x`-Variablen haben? Explizit auf »True« zu prüfen ist unnötig. Statt mit `round` zu runden, gibt man im Formatstring die Nachkommastellen an; literale Strings schreibt man direkt in den Formatstring. Eine feste Fenstergröße vorzugeben ist eine schlechte Idee; bei mir ist z.B. die Ergebniszeile halb abgeschnitten.

Um den Überblick in größeren Projekten zu behalten, darf man keine globalen Variablen benutzen. Das heißt auch, dass alles ab Zeile 44 in eine Funktion gehört und um die ganzen Entry-Variablen in die Funktionen zu bekommen, müßte man eigentlich auch eine Klasse mit Methoden schreiben. Scheinbar hattest Du auch diesen Gedanken, da alle Deine Funktionen ein nicht benutztes self-Argument haben (was eigentlich event heißen müßte, so wie sie benutzt werden).

Code: Alles auswählen

#!/usr/bin/python
# -- coding: utf-8 --
import Tkinter as tk
import tkSimpleDialog, tkMessageBox
 
class Verbrauchsrechner(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent
        tk.Label(self, text="gefahrene km").pack()
        self.km = tk.Entry(self, width=10, justify="center")
        self.km.pack()
        self.km.bind("<Return>", self.nextfield)
        
        tk.Label(self, text="getankte Liter").pack()
        self.liter = tk.Entry(self, width=10, justify="center")
        self.liter.pack()
        self.liter.bind("<Return>", self.ergebnis)
        
        tk.Label(self, text="Verbrauch:").pack()
        self.result = tk.Label(self, text="", font=('', 13, "bold"))
        self.result.pack()
        
        self.km.insert(0, "112,7")
        self.liter.insert(0, "6,5")
        self.km.focus()
        self.km.select_range(0, tk.END)
        
    def ergebnis(self, _event):
        try:
            km = float(self.km.get().replace(",", "."))
            liter = float(self.liter.get().replace(",", "."))
        except ValueError:
            self.result['text'] = "Zahl erwartet"
            self.result['fg'] = "red"
        else:
            if km > 50:
                verbrauch =  liter * 100 / km
                self.result['text'] = '{:.2f} Liter pro 100 km'.format(verbrauch)
                self.result['fg'] = "red" if verbrauch > 6 else "green"
            else:
                result = tkMessageBox.askyesno("Frage", "Fahren Sie noch ein paar km weiter, bis Sie den Verbrauch ausrechnen lassen!\n\nHaben Sie noch weitere Fragen?")
                if result:
                    tkMessageBox.showinfo("Info", "Dann machen wir hier weiter")
                    self.weiter()
                else:
                    tkMessageBox.showinfo("Info", "Dann machen wir hier Schluss")
                    self.parent.quit()
    
    def nextfield(self, _event):
        self.liter.focus()
        self.liter.select_range(0, tk.END)
 
    def weiter(self):
        # code für weiter hier
        tkMessageBox.showinfo("Info", "funktioniert!")

def main():
    root = tk.Tk()
    root.title("Benzinverbrauch")
    verbrauch = Verbrauchsrechner(root)
    verbrauch.pack()
    root.mainloop()
    
if __name__ == '__main__':
    main()
Axel-Erfurt
User
Beiträge: 20
Registriert: Mittwoch 2. Oktober 2013, 22:15

Wieso hat man beim Kopieren aus einer Python Codebox immer Leerzeichen am Anfang jeder Zeile?
Antworten