Listen, Schleifen, Wörterbücher und Abfragen

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
Mr. R341
User
Beiträge: 46
Registriert: Dienstag 29. September 2020, 10:51

Hallo :)

Wo fange ich an... Ich lerne gerade python und naja... ich soll eine einfache for/else schleife machen... das ist etwas ausgeartet, was aber an sich nicht schlimm ist.
Nun hatte ich die Idee ein Konsolenprogramm zum Bestellen in einem Restaurant zu machen.
Dieses hat wie man unten sieht viele Listen. Evtl. wollte ich daraus eine Variable "Speisekarte" machen, welche eine Liste der Gänge beinhaltet, welche wiederum ein Dictionary mit den Gerichten und deren Preis beinhaltet. So weit bin ich aber noch nicht.

Mein Problem besteht darin, dass ich eine Schleife machen will, welche erst abfragt, was man zum jeweiligen Gang essen will:

Code: Alles auswählen

for meal, dish in Bestellung.iteritems():
    Bestellung[meal] = raw_input("Was moechtest du zum/zur " + meal + " essen?: "  )
Das Ziel ist es, dass man etwas eingeben soll und das Programm dann überprüfen soll, ob dieses Gericht das man eingegeben hat auch in der Speisekarte bzw. in den Listen des jeweiligen Gangs enthalten ist. Ist dies der Fall, so soll die Schleife weitermachen. Sollte das Gericht aber nicht in dem jeweiligen Gang vertreten sein, so soll sie die Abfrage des selben Gangs wiederholen, bis man das Richtige eingegeben hat.

Code: Alles auswählen

    if any(item.lower() == Bestellung[meal].lower() for item in meal): 
        print Bestellung
    else:
        print("Dieses Gericht ist nicht verfügbar. Bitte wiederhole deine Eingabe..")
Ich bin total am verzweifeln und habe schon verschiedene Dinge ausprobiert.

Hier ist der gesammte Code:

Code: Alles auswählen

Vorspeise = set(Vorspeisen.lower() for Vorspeisen in(
"Suppe", "Flaedlesuppe", "Hawaitoast", "Antipasti", "", "", "", "Nichts"
))

Hauptgericht = set(Hauptgerichte.lower() for Hauptgerichte in(
"Steak", "Burger", "Pasta", "Pizza", "Kinderteller", "Seniorenteller", "", "Nichts",
))

Beilage = set(Beilagen.lower() for Beilagen in(
"Pommes", "Kartoffelecken", "Baguette", "", "", "", "", "Nichts",
))

Salat = set(Salate.lower() for Salate in(
"Kartoffelsalat", "Gurkensalat", "Schichtsalat", "", "", "", "", "Nichts",
))

Dessert = set(Desserts.lower() for Desserts in(
"Kuchen", "Torte", "Eis", "", "", "", "", "Nichts",
))

Getraenk = set(Getraenke.lower() for Getraenke in(
"Wasser", "Sprite", "Fanta", "Spezi", "Cola", "Eistee", "Apfelsaft", "Orangensaft", "Tee", "Kaffee", "", "", "Nichts",
))

Bestellung = {
  "Vorspeise" : None,
  "Hauptgericht": None,
  "Beilage": None,
  "Salat" : None,
  "Dessert": None,
  "Getraenk" : None,
  }

#for meal, dish in Bestellung.iteritems():
# Bestellung[meal] = raw_input("Was moechtest du zum/zur " + meal + " essen?: "  )
#else:
#  print "ERROR"

#print Bestellung


for meal, dish in Bestellung.iteritems():
    Bestellung[meal] = raw_input("Was moechtest du zum/zur " + meal + " essen?: "  )
    if any(item.lower() == Bestellung[meal].lower() for item in meal): 
        print Bestellung
    else:
        print("Dieses Gericht ist nicht verfügbar. Bitte wiederhole deine Eingabe..")
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Hallo,

ich wurde den Aufbau schon mal ändern, statt einzelner Listen mit dem Namen der Mahlzeit als Varaiblenname würde ich eher auf ein Dictionary setzen.
Dann eine Funktion welches eine Eingabe entgegen nimmt, prüft ob die gültig ist und wenn ja per return zurückgibt.

Code: Alles auswählen

MAHLZEITEN = {"Vorspeise":["Suppe", "Flaedlesuppe", "Hawaitoast", "Antipasti", "Nichts"],
              "Hauptgericht": ["Steak", "Burger", "Pasta", "Pizza", "Kinderteller", "Seniorenteller", "Nichts"],
              "Beilage":["Pommes", "Kartoffelecken", "Baguette", "Nichts"],
              "Salat":["Kartoffelsalat", "Gurkensalat", "Schichtsalat", "Nichts"],
              "Dessert":["Kuchen", "Torte", "Eis", "Nichts"],
              "Getränk":["Wasser", "Sprite", "Fanta", "Spezi", "Cola", "Eistee", "Apfelsaft", "Orangensaft", "Tee", "Kaffee", "Nichts"]}



def make_and_check_meal_input(meal):
    while True:
        choice = input(f"Was möchtest du als {meal}? Zu auswähl sind: [{', '.join(MAHLZEITEN[meal])}]: ")
        if choice in MAHLZEITEN[meal]:
            return choice
        else:
            print("Falsche Eingabe!")

def main():
    bestellung ={"Vorspeise" : None,
                 "Hauptgericht": None,
                 "Beilage": None,
                 "Salat" : None,
                 "Dessert": None,
                 "Getränk" : None}
    for meal, value in bestellung.items():
        bestellung[meal] = make_and_check_meal_input(meal)

    print(bestellung)

main()

Wenn Groß- und Kleinschreibung bei der Eingabe egal sein sollen, allerdings beim Output der Bestellung nicht, dann so:

Code: Alles auswählen

def make_and_check_meal_input(meal):
    while True:
        choice = input(f"Was möchtest du als {meal}? Zu auswähl sind: [{', '.join(MAHLZEITEN[meal])}]: ")
        if choice.lower() in [food.lower() for food in MAHLZEITEN[meal]]:
            for food in MAHLZEITEN[meal]:
                if choice.lower() == food.lower():
                    return food
        else:
            print("Falsche Eingabe!")
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Erstmal solltest Du nicht mehr Python2 lernen. Steig sofort auf Python3 um. Variablennamen werden komplett klein geschrieben. Konstanten komplett gross. Das hat ja Jankie schon gezeigt.
Seit Python 3.7 haben Wörterbücher auch eine feste Reihenfolge. Davor ist sie beliebig. Bei der Eingabe von Bestellung würdest Du dann auch das Dessert vor der Hauptspeise eingeben müsssen, oder so. Statt ein Wörterbuch mit Dummywerten anzulegen würde man über das MAHLZEITEN-Wörterbuch iterieren und daraus ein neues bestellung-Wörterbuch erzeugen.

Code: Alles auswählen

MAHLZEITEN = {
    "Vorspeise": ["Suppe", "Flaedlesuppe", "Hawaitoast", "Antipasti", "Nichts"],
    "Hauptgericht": ["Steak", "Burger", "Pasta", "Pizza", "Kinderteller", "Seniorenteller", "Nichts"],
    "Beilage": ["Pommes", "Kartoffelecken", "Baguette", "Nichts"],
    "Salat": ["Kartoffelsalat", "Gurkensalat", "Schichtsalat", "Nichts"],
    "Dessert": ["Kuchen", "Torte", "Eis", "Nichts"],
    "Getränk": ["Wasser", "Sprite", "Fanta", "Spezi", "Cola", "Eistee", "Apfelsaft", "Orangensaft", "Tee", "Kaffee", "Nichts"],
}

def input_meal(meal, choices):
    while True:
        choice = input(f"Was möchtest du als {meal}? Zur Auswahl stehen {', '.join(choices)}:")
        if choice in choices:
            return choice
        else:
            print("Falsche Eingabe!")

def main():
    bestellung ={}
    for meal, choices in MAHLZEITEN.items():
        bestellung[meal] = input_meal(meal, choices)
    print(bestellung)

if __name__ == '__main__':
    main()
Zuletzt geändert von Sirius3 am Dienstag 29. September 2020, 12:21, insgesamt 1-mal geändert.
Mr. R341
User
Beiträge: 46
Registriert: Dienstag 29. September 2020, 10:51

Wow... vielen Dank... aber leider sind da Dinge drinnen, die ich noch garnicht hatte...

zum einen: warum

Code: Alles auswählen

[{','.join()}] ?
was bewirkt das?

die Funktion "make_and_check_meal_input" habe ich verstanden. aber wann rufst die Funktion "main" auf?

als Letzte Frage hätte ich:
bei der for Schleife: warum genau braucht es die "value", wenn diese in der Schleife und im restlichen Code nicht mehr vor kommt? Oder ist das schonmal die Vorbereitung, wenn ich aus den Gerichten noch ein Dictionary mache welche Preise beinhalten?

MFG
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

@Mr. R341: In Jankies Code wird `value` gar nicht gebraucht. Ist wohl noch von einer früheren Version übrig (hast Du übrigens in Deinem Code genauso drin). Was eine bestimmte Methode macht, kann man entweder selbst ausprobieren oder in der Dokumentation nachlesen. `main` wird in der letzten Zeile aufgerufen.
Zuletzt geändert von Sirius3 am Dienstag 29. September 2020, 12:24, insgesamt 1-mal geändert.
Mr. R341
User
Beiträge: 46
Registriert: Dienstag 29. September 2020, 10:51

Danke Sirius. Aber leider ist mir das nicht möglich, da der python2 Kurs kostenlos ist und der Python3 Kurs nicht. daher und weil es meine erste Sprache ist, lerne ich Python2 und werde, nachdem ich diese kan mir ansehen und lernen, was die Unterschiede zu Python3 sind.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Dann such Dir einen anderen Kurs.
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Das bewirkt, dass eine Liste zu einem String wird, mit dem Komma als Trennzeichen zwischen den einzelnen Elementen. Also nur das ','.join(listenname). Die geschweiften Klammern darum sind wegen dem f-String dort, damit er erkennt, dass dort eine Variable ist.

Die Funktion main() gehört eigentlich wie bei Sirius3 Beispiel in einen if __name__ == '__main__': Block.

Bei meiner Version nutze ich die Varaible value nicht, da hast du Recht und die könnte weg. Sirius3 hat aber bei seinem Beispiel gezeigt wie es eleganter geht.

#edit: Ich habe mit dem offiziellen Python Tutorial gelernt, das ist meiner Meinung nach auch sehr gut. Gibt es in Deutsch (Python 3.3) und in Englisch
Mr. R341
User
Beiträge: 46
Registriert: Dienstag 29. September 2020, 10:51

Jankie hat geschrieben: Dienstag 29. September 2020, 12:25 Das bewirkt, dass eine Liste zu einem String wird, mit dem Komma als Trennzeichen zwischen den einzelnen Elementen. Also nur das ','.join(listenname). Die geschweiften Klammern darum sind wegen dem f-String dort, damit er erkennt, dass dort eine Variable ist.

Die Funktion main() gehört eigentlich wie bei Sirius3 Beispiel in einen if __name__ == '__main__': Block.

Bei meiner Version nutze ich die Varaible value nicht, da hast du Recht und die könnte weg. Sirius3 hat aber bei seinem Beispiel gezeigt wie es eleganter geht.

#edit: Ich habe mit dem offiziellen Python Tutorial gelernt, das ist meiner Meinung nach auch sehr gut. Gibt es in Deutsch (Python 3.3) und in Englisch
Und für was sind die Unterstriche?
Mr. R341
User
Beiträge: 46
Registriert: Dienstag 29. September 2020, 10:51

Gibt es eine Möglichkeit python Code direkt zu Coden und auszuführen, ohne jedes mal die .py erneut in IDLE zu öffnen und dann auszuführen?
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Anfangs habe ich in Notepad++ gecodet und dann die Datei übers Terminal aufgerufen. Du kannst aber auch eine Umgebung wie Visual Studio Code nutzen (mit der Pylance-Extension sehr hilfreich), allerdings musst du dich da dann auch in das Programm reinarbeiten.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ach herrje, hier ist noch der Tab mit der Antwort offen. Ist zwar alles schon gesagt worden, aber trotzdem:

@Mr. R341: Als allererstes solltest Du sofort aufhören Python 2 zu verwenden. Das ist seit Anfang des Jahres endgültig mausetot und riecht mittlerweile schon ein bisschen streng. 😉

Wenn man etwas wiederholen möchte, braucht man eine Schleife. In diesem Falle eine ``while``-Schleife. Da man am Anfang der Schleife noch nicht weiss ob im Schleifenkörper das richtige eingegeben wird, verwendet man eine ”Endlosschleife” (``while True:``) und wenn man in der Schleife dann festgestellt hat, dass man eine korrekte Eingabe bekommen hat, kann man die Schleife mit ``break`` verlassen.

Sonstige Anmerkungen zum Quelltext: Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

Eingerückt wird mit vier Leerzeichen pro Ebene.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Bei den Namen am Anfang ist Einzahl und Mehrzahl genau falsch herum. An `Vorspeise` wird eine Menge mit vielen Vorspeise*n* gebunden. In dem Generatorausdruck aus dem das `set` befüllt wird, wird dagegen der Name `Vorspeisen` für jeweils *eine* Vorspeise verwendet.

Letztlich ist das aber auch alles unnötig kompliziert geschrieben. Wenn man die Mengen mit den Wörtern mit Kleinbuchstaben füllen möchte, kann man das auch gleich so schreiben. Die teilweise mehrfachen leeren Zeichenketten gehören da nicht wirklich hinein, die werden a) vom `set()` zu einer leeren Zeichenkette verdichtet, und b) was soll dieser Wert dort bedeuten wenn es auch die explizite Auswahlmöglichkeit "Nichts" gibt? *Die* würde ich da auch nicht rein stecken. Denn die gibt es bei jedem Gang und kann deshalb direkt im Code berücksichtigt werden, der die Gänge erfragt.

Wenn man ein Wörterbuch erstellen will bei dem allen Schlüsseln der gleiche (unveränderbare) Wert zugewiesen wird, gibt es die `dict.fromkeys()`-Method:

Code: Alles auswählen

    bestellung = dict.fromkeys(
        [
            "Vorspeise",
            "Hauptgericht",
            "Beilage",
            "Salat",
            "Dessert",
            "Getränk",
        ]
    )
In der ``for``-Schleife wird `dish` gar nicht verwendet. Wäre ja auch sowieso jedes mal `None`. Letztlich kann/sollte man das Wörterbuch überhaupt nicht vorbefüllen, sondern eine Schleife über die zukünfigen Schlüssel schreiben.

Den eingegebenen Wert schon vor der Prüfung ob der gültig ist in `bestellung` zu stecken ist verfrüht.

Die ``if``-Bedinging ist vollkommen Unsinnig. Mach Dir mal klar was `meal` dort für einen Wert hat und gib daraufhin `item` einen *richtigen* Namen. Dann sollte das auffallen, dass das überhaupt keinen Sinn macht.

Zwischenstand:

Code: Alles auswählen

#!/usr/bin/env python3

VORSPEISEN = frozenset(["antipasti", "flaedlesuppe", "hawaiitoast", "suppe"])

HAUPTGERICHTE = frozenset(
    ["burger", "kinderteller", "pasta", "pizza", "seniorenteller", "steak"],
)

BEILAGEN = frozenset(["baguette", "kartoffelecken", "pommes"])

SALATE = frozenset(["gurkensalat", "kartoffelsalat", "schichtsalat"])

DESSERTS = frozenset(["eis", "kuchen", "torte"])

GETRAENKE = frozenset(
    [
        "apfelsaft",
        "cola",
        "eistee",
        "fanta",
        "kaffee",
        "orangensaft",
        "spezi",
        "sprite",
        "tee",
        "wasser",
    ],
)


def main():
    bestellung = {}
    for meal in [
        "Vorspeise",
        "Hauptgericht",
        "Beilage",
        "Salat",
        "Dessert",
        "Getränk",
    ]:
        while True:
            dish = input(f"Was möchtest du zum/zur {meal} essen? ")
            #
            # FIXME Diese Bedingung ist falsch.
            #
            if any(item.lower() == dish.lower() for item in meal):
                bestellung[meal] = dish
                print(bestellung)
                break

            print(
                "Dieses Gericht ist nicht verfügbar."
                " Bitte wiederhole deine Eingabe..."
            )


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Mr. R341
User
Beiträge: 46
Registriert: Dienstag 29. September 2020, 10:51

Danke blackjack. dein Beispiel zeigt mir, was ich vorher falsche gemacht hatte. Ich hatte im Dictionary vorher "key : " stehen und das wollte er nicht... daher hatte ich "None" eingetragen... dabei hätte ich einfach nur den Doppelpunkt weg lassen sollen :D

was ist genau ist frozenset()? heißt das einfach, dass die keys nicht mehr verändert werden können?
Dein Code ist allemal komplizierter, aber danke für deine schriftliche erklärung :)

Ich lerne es üner einen online kurs, bei dem man direkt auf der website seine Aufgaben codet... wenig lesen, viel schreiben...
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

@Mr. R341: __blackjack__ hat nicht einfach nur die Doppelpunkte weggelassen, sondern hat statt eines Wörterbuchs eine Liste für die Aufzählung der Gänge benutzt.
Mr. R341
User
Beiträge: 46
Registriert: Dienstag 29. September 2020, 10:51

@Sirius3: und wie erstelle ich ein Dictionary ohne values einzufügen?
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Wenn du die Keys in einer Liste hast:

Code: Alles auswählen

KEYS = ["Key1", "Key2", "Key3"]

leeres_dictioary_mit_keys = dict.fromkeys(KEYS)
print(leeres_dictioary_mit_keys)
Ansonsten wie hier gezeigt ein leeres Dictionary erzeugen und dann aufbauen.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Mr. R341 hat geschrieben: Dienstag 29. September 2020, 14:03 @Sirius3: und wie erstelle ich ein Dictionary ohne values einzufügen?
Gar nicht. Ein Wörterbuch ohne Werte macht keinen Sinn. Du erstellst das Wörterbuch erst, wenn Du den passenden Wert zu einem Schlüssel hast.
Antworten