Simple Logik If or will nicht

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
kani

Hier mal ein simples Beispiel:
Herraus kommt bei Days dann bei mir immer der falsche Wert 31Tage hat der April.
schon tage lang rumprobiert mit if /not /or komm nicht drauf warum!?

beispiel auszug aus mein Ziel zeit Rechner.

Code: Alles auswählen

month = 4 

if month == 1 or 3 or 5 or 7 or 8 or 10 or 12:
          days = 31
elif month == 4 or 6 or 9 or 11:
          days = 30
else:
          print ('fehler')
            
print (month)
print (days)
Zuletzt geändert von kani am Dienstag 18. April 2017, 13:51, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Liffi
User
Beiträge: 153
Registriert: Montag 1. Januar 2007, 17:23

kani hat geschrieben: month = 4

if month == 1 or 3 or 5 or 7 or 8 or 10 or 12:
days = 31
Ist immer wahr. Erste Abfrage ist: month == 1 -> wahr wenn month 1 ist. or 3 -> immer wahr. or 5 -> immer wahr...

Vielleicht willst du etwas benutzen wie:

Code: Alles auswählen

if month in [1, 3, 5, 7, 8, 10, 12]:
	days = 31
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

Was du wohl gemeint hast:

Code: Alles auswählen

if month == 1 or month == 3 or month == 5 or month == 7 or month == 8 or month == 10 or month == 12:
    days = 31
kani

Achja danke an alle hatte schon wieder vergessen das ich immer wieder month extra davorschreiben muss bei jeder einzelnen bedingung. (Bin noch beginner im Selbststudium da vergisst man schon mal sowas wichtiges wieder danke!)

Thema: Erledigt Kann geschlossen werden!

mfg Kani
BlackJack

@kani: Wenn der Fehlerzweig genommen wird, dann wird danach ja trotzdem noch versucht `days` auszugeben, was dann aber zu einem `NameError` führt. Das ist also irgendwie nur eine halbe Fehlerbehandlung.
kani

Stimmt BlackJack habs gemerkt das es noch nicht Funktioniert! Allerdings erst später g*!

Habe aber selbst eine lösung gefunden nach stunden langem rum probieren sogar mit Schaltjahr berücksichtigung bis Jahr xxxx. Allerdings mit viel schreiben/code das müste auch irgentwie einfacher gehen bzw. mit weniger code möglich sein. Aber egal hauptsache ich hab nen Funktioenierenden Code mit Python 3.6.:

Code: Alles auswählen

d = Tage
mo = monate
y = Jahr

if mo == 1:
          d = 31
elif mo == 2:
          if y == 2016:
                    d = 29
          elif y == 2020:
                    d = 29
          elif y == 2024:
                    d = 29
          elif y == 2028:
                    d = 29
          elif y == 2032:
                    d = 29
          elif y == 2036:
                    d = 29
          elif y == 2040:
                    d = 29
          elif y == 2044:
                    d = 29
          elif y == 2048:
                    d = 29
          elif y == 2052:
                    d = 29
          elif y == 2056:
                    d = 29
          elif y == 2060:
                    d = 29
          elif y > 2060:
                    d = 0000
          else:
                    d = 28
elif mo == 3:
          d = 31
elif mo == 4:
          d = 30
elif mo == 5:
          d = 31
elif mo == 6:
          d = 30
elif mo == 7:
          d = 31
elif mo == 8:
          d = 31
elif mo == 9:
          d = 30
elif mo == 10:
          d = 31
elif mo == 11:
          d = 30
elif mo == 12:
          d = 31
else:
          print ('Fehler Bitte geben Sie das nächste mal eine Zahl von 1-12 ein!')
dann kommt hier die ausgabe der Tage....
Liffi
User
Beiträge: 153
Registriert: Montag 1. Januar 2007, 17:23

Puh. Ein paar Tipps:
  • Variablen lieber nicht abkürzen
  • 0000 entspricht 0
  • Für Schaltjahre gibt es eine schöne Formel, mit der du wunderbar deine Kenntnisse über Verzweigungen benutzen kannst
  • Evtl. bietet sich für die 'einfachen' Monate auch ein dictionary an
BlackJack

@kani: Am kürzesten dürfte es mit `calendar.monthrange()` werden. :-)
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

Ich hatte etwas Zeit und wollte versuchen das "Tage_pro_Monat-Programm" (für meine Verhältnisse) einmal schön umzusetzen. Meint ihr das passt so oder würde man das mit Python anders lösen? Ist das dictionary in der get_days Funktion vielleicht doch nicht so geeignet?

Code: Alles auswählen

def main():
    while True:  
        try:
            month = int(input('Eingabe Monat: '))
            if 0 < month < 13: break
        except ValueError:
            print('Falsche Eingabe, erlaubt ist 1 - 12')
    
    # Jahrszahl nur für den Februar nötig
    if month == 2:
        while True:  
            try:
                year = int(input('Eingabe Jahr: '))
                if year > 0: break
            except ValueError:
                print('Falsche Eingabe, nur Zahlen erlaubt')
        output(month, get_days(month, year), year)
    else:
        output(month, get_days(month))
    
def get_days(month, year = None):
    '''Gibt die Anzahl der Tage von month zurück. year wird nur beim Monat Februar benötigt'''
    # Länge der Monate in einem dictionary speichern
    month_days = dict.fromkeys([1, 3, 5, 7, 8, 10, 12], 31)
    month_days.update(dict.fromkeys([4, 6, 9, 11], 30))
    month_days.update({2: {'is_leapyear': 29, 'no_leapyear': 28}})
    
    if year is None: # Für alle Monate außer Februar
        return month_days[month]
    elif month == 2 and year is not None: # Für den Februar
        if (year % 4 == 0 and year % 100 != 0) or (year % 4 == 0 and year % 100 == 0 and year % 400 == 0): #Schaltjahr
            leapyear = 'is_leapyear'
        else:
            leapyear = 'no_leapyear'
        return month_days[month][leapyear]
    else:
        return -1

def output(month, days, year = None):
    '''Gibt die Tage, den Monat und ggf. das Jahr ordentlich aus'''
    # dictionary mit den Monatsnamen
    month_names = {1: 'Januar', 2: 'Februar', 3: 'März', 4: 'April', 5: 'Mai', 6: 'Juni', 7: 'Juli', 8: 'August', 9: 'September', 10: 'Oktober', 11:'November', 12: 'Dezember'}  
    
    if year is None:
        print('Der {} hat {} Tage'.format(month_names[month], days))
    else:
        print('Der {} im Jahr {} hat {} Tage'.format(month_names[month], year, days))
  
if __name__ == '__main__':
 main()
Mir ist übrigens bewusst, dass man das Programm mit BlackJacks Vorschlag noch geringfügig kürzen kann :wink:

Code: Alles auswählen

import calendar  

month = int(input('Eingabe Monat: '))
year = int(input('Eingabe Jahr: '))

print(calendar.monthrange(year, month)[1])
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@Zizibee: es ist wohl nicht Absicht, dass bei Falscheingaben nicht immer die Fehlermeldung kommt. Die Funktion get_days ist seltsam, da sie bei month=2 nur mit year!=None funktioniert, für month!=2 aber nur mit year == None. Die if-Bedingung für ein Schaltjahr ist auch noch zu kompliziert. Außerdem wird das Wörterbuch für month == 2 ja nicht wirklich gebraucht. Statt -1 bei falschen Parametern sollte die Funktion auch eine Exception werfen.
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

@Sirius: Danke für die konstruktive Antwort!
Sirius3 hat geschrieben:es ist wohl nicht Absicht, dass bei Falscheingaben nicht immer die Fehlermeldung kommt.
Das ist mir zwar aufgefallen, aber leider ist mir keine Lösung eingefallen, um in try abzufragen, ob der Wert in einem bestimmten Wertebereich liegt und dann eine Exception zu werfen :K
Sirius3 hat geschrieben:Die Funktion get_days ist seltsam, da sie bei month=2 nur mit year!=None funktioniert, für month!=2 aber nur mit year == None.
Da hast du wohl recht, das ist zum Anwenden umständlich und kompliziert. Werde ich überarbeiten
Sirius3 hat geschrieben:Die if-Bedingung für ein Schaltjahr ist auch noch zu kompliziert.
Jetzt da du es sagst... aber bestimmt hast du noch mehr gesehen als ich :wink:
Sirius3 hat geschrieben:Außerdem wird das Wörterbuch für month == 2 ja nicht wirklich gebraucht. Statt -1 bei falschen Parametern sollte die Funktion auch eine Exception werfen.
Das month == 2 kam erst rein, als ich Fehler abfangen wollte und das return -1 hinzu kam. Das werde ich zusammen mit der kompletten Funktion überarbeiten.
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

Ich habe die Punkte überarbeitet und denke bzw. hoffe, dass es jetzt passt.

Der try... except Block für die Eingabe wurde angepasst und der Wertebereich wird jetzt über einen AssertionError abgefangen. Ich hoffe ich habe sie im Sinne des Erfinders angewendet.

Code: Alles auswählen

def main():
    while True:  
        try:
            month = int(input('Eingabe Monat: '))
            assert 0 < month < 13
            break
        except ValueError:
            print('ValueError: Falsche Eingabe, es sind nur ganze Zahlen erlaubt')
        except AssertionError:
            print('AssertionError: Falsche Eingabe, erlaubt ist 1 - 12')

    # Jahrszahl ist nur für den Februar nötig
    if month == 2:
        while True:  
            try:
                year = int(input('Eingabe Jahr: '))
                assert year > 0
                break
            except ValueError:
                print('Falsche Eingabe, es sind nur ganze Zahlen erlaubt')
            except AssertionError:
                print('Falsche Eingabe, es sind nur positive Zahlen erlaubt')

        output(month, get_days(month, year), year)
    else:
        output(month, get_days(month))

Die Funktion get_days() akzeptiert nun bei allen Monaten Jahreszahlen und sollte dadurch robuster in der Anwendung sein. Zusätzlich erhält man bei einem fehlerhaften Aufruf keine -1 mehr als Rückgabewert, sondern es wird eine Exception geworfen. Auch wurde die Bedingung für das Schaltjahr vereinfacht.

Code: Alles auswählen

def get_days(month, year = None):
    '''Gibt die Anzahl der Tage von month zurück. year wird nur beim Monat Februar benötigt'''
    # Länge der Monate in einem dictionary speichern
    month_days = dict.fromkeys([1, 3, 5, 7, 8, 10, 12], 31)
    month_days.update(dict.fromkeys([4, 6, 9, 11], 30))
    month_days.update({2: {'is_leapyear': 29, 'no_leapyear': 28}})
    
    if month == 2:
        try:
            if (year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)): #Schaltjahr
                leapyear = 'is_leapyear'
            else:
                leapyear = 'no_leapyear'
            return month_days[month][leapyear]
        except TypeError:
            print('Error in get_days(), fehlende Jahreszahl bei Februar => Jahr wird auf "kein Schaltjahr" gesetzt')
            return month_days[month]['no_leapyear']
    else:
        return month_days[month]

An der Ausgabe habe ich nichts geändert.
__deets__
User
Beiträge: 14536
Registriert: Mittwoch 14. Oktober 2015, 14:29

Assertions sind nicht fuer so etwas gedacht. Man kann sie naemlich auch automatisch rausschmeissen, wenn man pyo (optimierte Python Bytecode Dateien) erzeugt.

Stattdessen eine einfach Abfrage "if year <= 0" machen.

Und statt string-Konstanten in leapyear einfach

Code: Alles auswählen

is_leapyear =  (year % 4 == 0 and (year % 100 != 0 or year % 400 == 0))
und dann einfach das dict von "is_leapyear": 29 auf True: 29 aendern.
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

__deets__ hat geschrieben:Assertions sind nicht fuer so etwas gedacht. Man kann sie naemlich auch automatisch rausschmeissen, wenn man pyo (optimierte Python Bytecode Dateien) erzeugt.

Stattdessen eine einfach Abfrage "if year <= 0" machen.
Also dann so in der Art? Auch wenn dann für den Wertebereich streng genommen keine Exception geworfen wird?

Code: Alles auswählen

try:
    month = int(input('Eingabe Monat: '))
    is 0 < month < 13:
        break
    else:
        print('Falsche Eingabe, erlaubter Zahlenbereich ist 1 - 12')
except ValueError:
    print('ValueError: Falsche Eingabe, es sind nur ganze Zahlen erlaubt')

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

Eine Exception ist doch kein Selbstzweck. Wenn du willst, kannst du natuerlich im else-Zweig ebenfalls einen ValueError werfen, und dann deine Fehlermeldung entsprechend so aendern, dass es nur noch heisst "Falsche Eingabe, es sind nur ganze Zahlen von 1 - 12 erlaubt".

Das "ValueError: " in der Fehlermeldung bei dir wuerde ich mir uebrigens sparen, damit kann kein Benutzer etwas anfangen. Der Rest der Meldung reicht.
Antworten