how do I format a nested if-else statement in python to make it work?

Question:

I am taking a intro to scripting class and have a prompt to make a program that will accept an input month and then an integer day and tell what season it falls in, or to write ‘Invalid’ if the input fails to meet the criteria (zybooks lab 3.12.1). I have seen some examples of this, but they wrote this a different way, and I want to learn this, not copy already solved problems. I defined my inputs, made a list of acceptable string inputs to check from, then further broke the list down into months by how many days are in them. I set checks to make sure the input int value falls within the range of the month entered, and set that value to True if it passed the check. Relevant code follows:

input_month = input()
input_day = int(input())

months_list = [
    'January', 'February',
    'March', 'April', 'May',
    'June', 'July', 'August',
    'September', 'October',
    'November', 'December']

day30_months = (months_list[3], months_list[5], months_list[8], months_list[10])
day31_months = (months_list[0], months_list[2], months_list[4], months_list[6], months_list[7],
                months_list[9], months_list[11])
day29_months = (months_list[1])

if input_month not in months_list:
    print('Invalid')

if input_month in day30_months and 0 < input_day <= 30:
    input_day = True

if input_month in day31_months and 0 < input_day <= 33:
    input_day = True

if input_month in day29_months and 0 <= input_day <= 29:
    input_day = True

if input_month == 'March':
    if input_day == True:
        if input_day <= 19:
            print('Winter')
        else:
            print('Spring')
    else:
        print('Invalid')

if input_month in ('April', 'May'):
    if input_day == True:
        print('Spring')
    else:
        print('Invalid')

So far everything works and I like this route, but my second nested function under ‘March’ doesn’t work. If my input is ‘March’ and ’35’, it prints Invalid. If my input is ‘March’ and ’11’, it prints Winter. But for some reason if I input ‘March’ and ’22’, it prints Winter, and I don’t know why it doesn’t move on to the else condition after the true check for input_day and a value greater than 20.
Can someone tell me why? I can’t find an answer for why this won’t fail the input_day <= 19 check and print ‘Spring’.
Also, PyCharm tells me that the lines for "if input_day == True" can be simplified, but it doesn’t tell me how.
Thanks.

Asked By: VandalEvil

||

Answers:

So from what I can tell you are having trouble with the stuff under the March check and why it thinks 22 is smaller or equal to 19.

Well, that is because you check if the input_day variable is smaller or equal to 19, however before checking you also seem to set that to True, a boolean value. The way bools work in Python is that the False and True keywords are placeholders for the integers 0 and 1 respectively, and seeing as both of those are smaller than 19 your issue surfaces.

Example:

var = True
if var <= 1: # This will always trigger since var is technically equal to 1.
    print("Here")

The fix would be to use a different variable there.

About PyCharm telling you that the == True part can be simplified, that’s just because the if command works by checking if the condition is True. This means that if your variable is already either True or False, there is no need to check if it is equal to that (even if its more intuitive to do so), but that’s really just at best a nitpick and at worst a small waste of time.

Answered By: Duhon

But for some reason if I input ‘March’ and ’22’, it prints Winter, and I don’t know why it doesn’t move on to the else condition after the true check for input_day and a value greater than 20. Can someone tell me why?

The reason for this behavior is that you overwrite the integer value of the input_day if it is 22 with the value True in your code. In Python True is equivalent to 1 (one) so later in the code 1 <= 19 gives Winter.

Replace all of the input_day with day_OK if you check for validity of the day and you will get the expected behavior.

Don’t forget to set day_OK=False first, then if you check validity set day_OK=True and use:

if input_month == 'March':
    if day_OK: # means the same as day_OK == True
        if input_day <= 19:
            print('Winter')
        else:
            print('Spring')
    else:
        print('Invalid')

But … best you rewrite your code as suggested by Barmar in the comment to your question.

Here how it can look like after such rewrite:

input_month = input()
input_day = int(input())

months_list = [
    'January', 'February',
    'March', 'April', 'May',
    'June', 'July', 'August',
    'September', 'October',
    'November', 'December']

day30_months = (months_list[3], months_list[5], months_list[8], months_list[10])
day31_months = (months_list[0], months_list[2], months_list[4], months_list[6], months_list[7],
                months_list[9], months_list[11])
day29_months = (months_list[1])

if input_month not in months_list:
    print('Invalid month', input_month)

day_OK=False

if   input_month in day30_months and 0 < input_day <= 30:
    day_OK = True
elif input_month in day31_months and 0 < input_day <= 31:
    day_OK = True
elif input_month in day29_months and 0 < input_day <= 29:
    day_OK = True
else:
    print('Invalid day for', input_month)
    
if day_OK and input_month == 'March':
    if input_day <= 19:
        print('Winter')
    else:
        print('Spring')

if day_OK and input_month in ('April', 'May'):
    print('Spring')

The next step of improvement of your code could be usage of a dictionary for the months and days in a month making the code simpler and shorter:

dict_months = {
    'January':31, 'February':29, 'March':31, 'April':30, 'May':31,
    'June':30, 'July':31, 'August':31, 'September':30, 'October':31,
    'November':30, 'December':31
    }
month_OK=False
day_OK=False

input_month = input()
input_day = int(input())

if input_month in dict_months:
    month_OK=True
else:
    print('Invalid month', input_month)
if month_OK and 0 < input_day <= dict_months[input_month]:
    day_OK = True
else:
    print('Invalid day',input_day,'for', input_month)

if day_OK and input_month == 'March':
    if input_day <= 19:
        print('Winter')
    else:
        print('Spring')

if day_OK and input_month in ('April', 'May'):
    print('Spring')

With dictionary values as tuples listing days of the month and the given month preceding days in the year it would be possible to determine from the user input the day of the year what would cut the following if-conditions to four for the four year seasons:

dict_months = {
    'January':(31,0), 'February':(29,31), 'March':(31,60),
    'April':(30,91), 'May':(31,121), 'June':(30,152),
    'July':(31,182), 'August':(31,213), 'September':(30,244),
    'October':(31,274), 'November':(30,305), 'December':(31,335)
    }

month_OK=False
day_OK=False

input_month = input()
input_day = int(input())

if input_month in dict_months:
    month_OK=True
else:
    print('Invalid month', input_month)
    

if month_OK and 0 < input_day <= dict_months[input_month][0]:
    day_OK = True
else:
    print('Invalid day',input_day,'for', input_month)

if day_OK and month_OK:
    day_of_year = dict_months[input_month][1]+input_day 
    if   day_of_year <= 79 or day_of_year >= 356:
        print('Winter')
    if  80 <= day_of_year <= 172:
        print('Spring')

Answered By: Claudio
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.