Variablen in if-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
qiwi
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 10:16

Hallo,
noch ein Neuling in Python. Habe aber schon einiges in PHP geschrieben.
Aus diesem Grunde hänge ich eben fest - ich versuche über eine if-Abfrage bestimmten Variablen einen Wert zuzuweisen.
Hier reagiert Python jedoch anders - ich bekomme die in der if-Abfrage erstellte Variable nicht außerhalb ausgegeben.
Als Fehlermeldung bekomme ich "not definded".
Nun habe ich gegoogelt aber leider finde ich nur jede Menge Beispiele, wie man in der if-Abfrage ein print() ausgibt.
Also nach dem Motto

Code: Alles auswählen

if planet==1
print("Planet 1")
Ich jedoch möchte in der Abfrage bestimmten Variablen einen Wert zuweisen - je nachdem was vorher über die input() Funktion eingegeben wurde.
Hier mein kleines Testprogramm.

Code: Alles auswählen

def summe (u,kmh):
    zeit = round(u / kmh)
    return zeit
print ("Bitte Ihre Durchschnitts-Geschwindigkeit eingeben:")
kmh = input()
k = int(kmh)
print("Auf welchem Planeten möchten Sie mit dem Auto fahren?")
print("1=Merkur")
print("2=Venus")
print("3=Erde")
print("4=Mars")
print("5=Unser Mond")
planet=input()
if planet==1:
    plu=15329
    pln="Merkur"
    plf="den"
elif planet==2:
    plu=38025
    pln="Venus"
    plf="die"
elif planet==3:
    plu=40075
    pln="Erde"
    plf="die"
elif planet==4:
    plu=21344
    pln="Mars"
    plf="den"
elif planet==5:
    plu=10921
    pln="Erdenmond"
    plf="den"
ergebnis = summe(plu,k)
if ergebnis==1:
    stunde="Stunde"
else:
    stunde="Stunden"
print ("Sie benötigen",ergebnis,stunde,"um mit dem Auto um",plf,pln,"zu fahren")
Kann Python nur ein print() in einer if-Abfrage ausgeben? Google hat mir jedefalls nur jede Menge dieser
Beispiele angezeigt.

Vielen Dank im Voraus

Sven
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst beliebige Anweisungen ausführen innerhalb eines if-Blocks. Und natürlich auch Werte an Namen binden. Was passiert denn was du nicht erwartest?

Deine Benamungen sind übrigens sehr schlecht. Dreibuchstabige Abkürzungen bei denen du auch noch zwei für einen redundanten Präfix verwendest sind schwer entzifferbar. Warum nicht name, umfang und artikel?

Und da in ‚summe‘ keine solche berechnet wird, ist das auch ein schlecht gewählter Name.
qiwi
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 10:16

Du hast recht - die Namen sind schlecht gewählt. Das habe ich auch geändert.
Mein Problem ist aber, dass ich den Wert der Variablen am Ende des Programms nicht ausgeben kann weil diese Variablen nicht definiert sind.
Was ist an meiner Variablen-Definition in den Abfragen denn falsch?

Danke
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Zeig bitte den genauen Code & die dazu passende Fehlermeldung. Sonst ist das schwer zu beantworten.
qiwi
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 10:16

Die genaue Fehlermeldung lautet:

Traceback (most recent call last):
File "C:/Python36/Beispiele/funktion1.py", line 34, in <module>
ergebnis = zeit(umfang,k)
NameError: name 'umfang' is not defined

Jetzt natürlich mit dem Namen umfang und nicht mehr plu.
Der Code steht oben - oder habe ich hier auch was falsch gemacht?

Besser noch einmal der ganze Code:

Code: Alles auswählen

def zeit (umfang,k):
    zeit = round(umfang / kmh)
    return z
print ("Bitte Ihre Durchschnitts-Geschwindigkeit eingeben:")
kmh = input()
k = int(kmh)
print("Auf welchem Planeten möchten Sie mit dem Auto fahren?")
print("1=Merkur")
print("2=Venus")
print("3=Erde")
print("4=Mars")
print("5=Unser Mond")
planet=input()
if planet==1:
    umfang=15329
    name="Merkur"
    artikel="den"
elif planet==2:
    umfang=38025
    name="Venus"
    artikel="die"
elif planet==3:
    umfang=40075
    name="Erde"
    plf="die"
elif planet==4:
    umfang=21344
    name="Mars"
    artikel="den"
elif planet==5:
    umfang=10921
    name="Erdenmond"
    artikel="den"
ergebnis = zeit(umfang,k)
if ergebnis==1:
    stunde="Stunde"
else:
    stunde="Stunden"
print ("Sie benötigen",ergebnis,stunde,"um mit dem Auto um",artikel,name,"zu fahren")


    


Benutzeravatar
DeaD_EyE
User
Beiträge: 1017
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Da sind zu viele if-abfragen wo man leicht den Überblick verlieren kann.
Ich würde die eigentlich Abfrage so gestalten:

Code: Alles auswählen

from collections import namedtuple


Planet = namedtuple('Planet', 'plu pln plf')
planets = [
    Planet(15329, 'erde', 'den'),
    Planet(38025, 'venus', 'die'),
    Planet(40075, 'erde', 'die'),
    Planet(21344, 'mars', 'den'),
    Planet(10921, 'erdenmond', 'den'),
]

def get_input(planets):
    while True:
        for n, planet in enumerate(planets, start=1):
          print(f'{n} Planet: {planet.pln.title()}')
        selection = input('Bitte einen Planeten angeben: ')
        try:
            planet = planets[int(selection.strip()) - 1]
        except (ValueError, IndexError):
            print('Falsche Angabe.')
            continue
        return planet
Für Planet bitte bessere Variablennamen auswählen.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@qiwi: alles was eingegeben wird, ist vom Typ String, Du vergleichst aber mit Zahlen, das kann nie funktionieren. Um solche Fehler leichter zu finden, ist es immer gut, einen else-Block zu haben, bei dem eine aussagekräftige Fehlermeldung ausgegeben wird.

@DeaD_EyE: warum schreibst Du alle Planetennamen klein und benutzt dann title? Ein `strip` ist bei `int` schon integriert. Wenn Du im try-Block return verwenden würdest, bräuchtest Du im except kein continue.
qiwi
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 10:16

@DeaD_EyE: Danke - aber so weit bin ich noch nicht - sicher könnte ich mir das nun abtippen - weiß aber nicht, was ich da eigentlich mache.

@Sirius3
Ich habe doch k umgewandelt - alles andere wird ja nicht berechnet.

Code: Alles auswählen

k = int(kmh)
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Aber deine Planeten Auswahl soll doch auch ein int sein. Wandeltest du aber nicht um.
qiwi
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 10:16

Ich dachte umfang=12345 ist schon ein int und kein String - ok dann liegt hier der Fehler.
Ich dachte nur "Dinge in Anführungszeichen" ist ein String.

Ich versuche das mal.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Der Punkt ist deine Anfrage welcher Planet es sein soll. 1-5. Input liefert einen String. Du vergleichst aber mit einem int. Da kommt nix bei rum. Also denkt dein Programm es gab gar keine Eingabe die passend war, und keine Variable wird halt definiert.
qiwi
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 10:16

Jetzt habe ich es verstanden - da liegt der Fehler. Klar - logisch wenn man es weiß :D
Ich frage nach einem int die Eingabe ist aber ein String.

Vielen Dank :)
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

qiwi hat geschrieben:noch ein Neuling in Python. Habe aber schon einiges in PHP geschrieben.
Ein Unterschied zwischen Python und PHP ist, dass in Python viel Wert auf Transparenz gelegt wird; Python versucht nicht zu raten, was der Benutzer gemeint habe könnte. Wenn ein String wie ein Integer verwendet werden soll, macht Python das nur, wenn man es ihm sagt und im allgemeinen gilt das als sauberer.
Vielleicht hilft das besser zu verstehen, warum der Fehler entstanden ist und ähnliche zukünftig zu vermeiden.
qiwi
User
Beiträge: 8
Registriert: Montag 5. Februar 2018, 10:16

Nun habe ich das auch getan - ich habe dem input gesagt Du bist ein integer.

Code: Alles auswählen

def zeit (umfang,k):
    zeit = round(umfang / k)
    return zeit
print ("Bitte Ihre Durchschnitts-Geschwindigkeit eingeben:")
kmh = input()
k = int(kmh)
print("Auf welchem Planeten möchten Sie mit dem Auto fahren?")
print("1=Merkur")
print("2=Venus")
print("3=Erde")
print("4=Mars")
print("5=Unser Mond")
planet=int(input())
if planet==1:
    umfang=15329
    name="Merkur"
    artikel="den"
elif planet==2:
    umfang=38025
    name="Venus"
    artikel="die"
elif planet==3:
    umfang=40075
    name="Erde"
    artikel="die"
elif planet==4:
    umfang=21344
    name="Mars"
    artikel="den"
elif planet==5:
    umfang=10921
    name="Erdenmond"
    artikel="den"
else:
    umfang=1111
    name="WTF"
    artikel="dessss"
    
ergebnis = zeit(umfang,k)
if ergebnis==1:
    stunde="Stunde"
else:
    stunde="Stunden"
print ("Sie benötigen",ergebnis,stunde,"um mit dem Auto um",artikel,name,"zu fahren")
Und schon funktioniert es.

Danke Euch allen!!!
Benutzeravatar
DeaD_EyE
User
Beiträge: 1017
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Sirius3 hat geschrieben:@DeaD_EyE: warum schreibst Du alle Planetennamen klein und benutzt dann title? Ein `strip` ist bei `int` schon integriert. Wenn Du im try-Block return verwenden würdest, bräuchtest Du im except kein continue.
Weil ich erst mit einem dict angefangen habe und die Angewohnheit habe alle Keys klein zu schreiben.
Dann viel mir auf, dass eine Liste einfacher ist, habe die Namen dann trotzdem nicht geändert.

Das mit int wusste ich nicht. Der filtert ja alle Whinespaces: int('\n\n\n\n \t 4\t\r')
Das mit dem try-Block ist Absicht. Man sollte return statements in try-Blöcken vermeiden. Das sagte Alex Martelli in einem Vortrag.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
narpfel
User
Beiträge: 645
Registriert: Freitag 20. Oktober 2017, 16:10

@DeaD_EyE: Hast du da eine Quelle zu, dass `return`s in `try`-Blöcken vermieden werden sollten? Eventuell auch eine, die Gründe angibt?

Was macht es für einen Sinn, alle `dict`-Schlüssel klein zu schreiben?
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

narpfel hat geschrieben:@DeaD_EyE: Hast du da eine Quelle zu, dass `return`s in `try`-Blöcken vermieden werden sollten? Eventuell auch eine, die Gründe angibt?
Das würde mich auch interessieren. Alex Martelli nutzt dieses Konstrukt in seinem Buch "Python in a Nutshell" übrigens selbst.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

narpfel hat geschrieben: Was macht es für einen Sinn, alle `dict`-Schlüssel klein zu schreiben?
Ohne Dead_Eye zu sein: weil in Python Argumente klein geschrieben werden, und weil man dicts kompakter so schreibt:

Code: Alles auswählen

dict(schluessel="wert")
statt das rumgefummel mit "". Mache ich zumindest so, und da kann sowas dann mental eingebaut werden.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1017
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

narpfel hat geschrieben:@DeaD_EyE: Hast du da eine Quelle zu, dass `return`s in `try`-Blöcken vermieden werden sollten? Eventuell auch eine, die Gründe angibt?

Was macht es für einen Sinn, alle `dict`-Schlüssel klein zu schreiben?
Keys in dicts klein zu schreiben ist meine Vorliebe. Wie ihr das macht, liegt an eurem Geschmack bzw. den Vorgaben.

Das mit dem return-statement im Try-Block ist wenn ich mich richtig erinnere in eins dieser beiden Videos angesprochen worden:
https://www.youtube.com/watch?v=frZrBgWHJdY
https://www.youtube.com/watch?v=_Ek3A2b-nHU

Wenn du in deinem Code mehrere try-except-blöcke hast, wird es schnell unübersichtlich.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
narpfel
User
Beiträge: 645
Registriert: Freitag 20. Oktober 2017, 16:10

@DeaD_EyE: Ich hab’ mir jetzt nicht die 1,7 Stunden an Videos angesehen, aber in den Folien findet man das, das, das und das.

Kann es sein, dass er gesagt hat, dass man `return` nicht innerhalb von `finally`-Blöcken verwenden sollte? Das ist einfach nachvollziehbar, oder kannst du mir sagen, was das hier zurückgibt:

Code: Alles auswählen

def foo():
    try:
        1 / 0
        return 15
    except ZeroDivisionError:
        return 27
    finally:
        return 42
Falls es nicht so gemeint war, müsstest du den Quellenraum auf weniger als 1,7 Stunden einschränken. :wink:
Antworten