Python Forum
My else clause doesn't work (general help)
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
My else clause doesn't work (general help)
#1
I'm following a Python tutorial, and in one of the exercises I have to:
Quote:Assume the days of the week are numbered 0,1,2,3,4,5,6 from Sunday to Saturday. Write
a program that asks a day number, and prints the day name (a string).

Even though I didn't have to, I created a variable with the days of the week, and their corresponding number, and coded what was asked. My code looks like this:

days = [(0, "Sunday"), (1,"Monday"), (2,"Tuesday"), (3,"Wednesday"),
        (4, "Thursday"),(5, "Friday"),(6,"Saturday")]
num_inp= int(input("What's the day number?"))
for number, name in days:
   if num_inp == number:
       print (name)
This works, for example with an input =3, I get an output:
Quote:What's the day number?3
Wednesday


However, when I want to add an else clause to print "invalid day" or something like that when the user would input a number outside of the given number range, like this:
days = [(0, "Sunday"), (1,"Monday"), (2,"Tuesday"), (3,"Wednesday"),
        (4, "Thursday"),(5, "Friday"),(6,"Saturday")]
num_inp= int(input("What's the day number?"))
for number, name in days:
   if num_inp == number:
       print (name)
   else:
       print ("There is no such day")
.. the program does what I tell it to do, .... which is basically loop 7 times, to basically return 7times "There is no such day". But that is not what I want it to do. I want just one "There is no such day return" in case of an invalid day number. Even when I would input a valid day number now, it still loops seven times to now return  6 times "There's no such day", and one valid day number. Adding a break statement to the else clause doesn't help either.

output:
Quote:What's the day number?3
There is no such day
There is no such day
There is no such day
Wednesday
There is no such day
There is no such day
There is no such day

Help....! :-)
Reply
#2
here's another way to do it
def guess_day():
   days = days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
   forever = 1
   while forever:
       max_day = len(days)

       num_inp = int(input("What's the day number (1-7)? "))
       if num_inp < 1 or num_inp > max_day:
           print('Sorry day out of range, try again')
       else:
           print('num_inp: {} is {}'.format(num_inp, days[num_inp - 1]))
           break

if __name__ == '__main__':
   guess_day()
Reply
#3
You really want the else statement on the for. That is, if the for loop does not find anything, you want to print there is no such day. The old way to do this uses a boolean variable:

day_found = False
for number, name in days:
    if num_inp == number:
        print(name)
        day_found = True
        break
if not day_found:
    print('There is no such day.')
Notice the break statement. Once we find the correct day (if there is one), there's no point in processing further. So we use the break statement to break out of the loop.

Python gives us a simpler way to do this, using that break statement. It allows us to put the else statement on the for loop. Then if the for loop finishes without a break statement, whatever code is in the else statement executes:

for number, name in days:
    if num_inp == number:
        print(name)
        break
else:
    print('There is no such day.')
This set of code works the same as the previous set of code, but you don't have to track a separate variable.

That solves the problem as you were looking at it, but the real problem is that you need a better data structure. A dictionary would be ideal here:

day_dict = dict(days)
if num_inp in day_dict:
    print(day_dict[num_inp])
else:
    print('There is no such day.')
The first line creates a dictionary where the keys are the first item in each tuple (the numbers) and the values are the second item in each tuple (the day names). The if statement checks to see if num_inp is one of the keys (and thus a valid day). If it is valid, the next line pulls the value from the dictionary using the key (num_inp). If you're not following this, there is a tutorial on dictionaries in the tutorials section.

And while it may not be ideal, you can also solve this problem with a list:

days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
print(days[num_inp])
Now you get an error raised for an invalid day. You can either handle that error, pass it on, or prevent it by checking that the day number is between 0 and 6 before printing.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#4
(Jul-15-2017, 01:23 PM)Larz60+ Wrote: here's another way to do it
def guess_day():
    days = days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
    forever = 1
    while forever:
        max_day = len(days)

        num_inp = int(input("What's the day number (1-7)? "))
        if num_inp < 1 or num_inp > max_day:
            print('Sorry day out of range, try again')
        else:
            print('num_inp: {} is {}'.format(num_inp, days[num_inp - 1]))

if __name__ == '__main__':
    guess_day()

Thanks.. I see how this could work, even though I don't really know what {} or '_main_' means yet (I'm not that far in the tutorial...lol). However, I do know that we're advised to only use while when you don't exactly know how many times the program is going to loop. In this case you do know, so would an "if" statement have worked, too in stead of while?

Quote:
(Jul-15-2017, 01:27 PM)ichabod801 Wrote: You really want the else statement on the for. That is, if the for loop does not find anything, you want to print there is no such day. The old way to do this uses a boolean variable:

Python gives us a simpler way to do this, using that break statement. It allows us to put the else statement on the for loop. Then if the for loop finishes without a break statement, whatever code is in the else statement executes:

for number, name in days:
    if num_inp == number:
        print(name)
        break
else:
    print('There is no such day.')
This set of code works the same as the previous set of code, but you don't have to track a separate variable.

Quote:That solves the problem as you were looking at it, but the real problem is that you need a better data structure. A dictionary would be ideal here:


Thanks, initially I tried to incorporate a break statement, too (see OP), but I had put the break in the else clause block and not in the if block. And I also did to place the else clause outside of the if-statement, but sincewithout that break, it still didn't do what I wanted it to do. This script is what I understand the best right now, with my limited knowledge of Python. Thanks again.


Thanks, when I'm a bit further with the tutorial, I'll come back to this exercise and try implementing a better data structure through implementing a dictionary

\
Reply
#5
What previous posters didn't include is why you get that output.

for number, name in days: means for every number, name value in days it will print name if your input equals number, else it will printThere is no such day.
In your example, input is 3: For 0, "Sunday" 3!= 0; output. For 1,"Monday" 3!= 1; output. For 2,"Tuesday" 3!= 2; output. For 3,"Wednesday" 3 == 3; output. For 4, "Thursday" 3!= 4; output. Etc.

By moving the else statement out of the for loop it never hits the else until the loop ends. By putting the break in the if statement it stops the loop when the if is satisfied. This way, it only prints once. Without the break, if the if is satisfied, it processes, the loop finishes, and unless your input is 6, the else is satisfied and it processes. (At the end of the loop, number, name == 6,"Saturday")
Reply
#6
I added a break statement and comments
I also reworked user input to require valid input
and let you know when you try too many times
def guess_day():
    days = days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']

    max_tries = 7

    # The for statement iterates through a collection or iterable object or generator function.
    # The while statement simply loops until a condition is False. while 1 (which is forever)
    while 1:
        # Max_day used as a validity check for users entry
        max_day = len(days)
        # set num_input to non valid number to force one iteration
        num_inp = -1
        num_tries = 0

        # num_inp for users guess
        while num_inp < 1 or num_inp > max_day:
            # check validity of input. skip error if first try, this is a trick
            if num_inp != -1:
                print('Sorry day out of range, try again')
                # increment num_tries
                num_tries += 1
                if num_tries >= max_tries:
                    # set numtries = 99, used to flag fatal error, then break while loop
                    num_tries = 99
                    break
            num_inp = int(input("What's the day number (1-7)? "))

        if num_tries == 99:
            print('bist du ein dummkopf')
            break
        # here num_inp = index to week day name +1 (so it will start with 1 on the input) so that number is used to fetch dat
        print('num_inp: {} is {}'.format(num_inp, days[num_inp - 1]))


if __name__ == '__main__':
    guess_day()
Reply
#7
Some points Larz60+ Wink
Quote:while 1 (which is forever)

forever = 1
   while forever:
So two ways in this post,the way it should is while True:

Just to solve the task.
def guess_day():
   days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
   day_inp = int(input("What's the day number (1-7)? "))
   for day in days:
       if 1 <= day_inp >= 7:
           return('Day out of range 1-7,try again')
       else:
           return('Day: {} is {}'.format(day_inp, days[day_inp-1]))
Look at if 1 <= day_inp >= 7: no or.
That comparisons can be chained is easy to forget or not know,maybe and or can be equally clear,
because is used more.
Reply
#8
(Jul-16-2017, 09:10 PM)snippsat Wrote: Look at if 1 <= day_inp >= 7: no or.

Also equivalent to if day_inp >= 7. I think you meant if 1 <= day_inp <= 7.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#9
Quote:Also equivalent to if day_inp >= 7. I think you meant if 1 <= day_inp <= 7.
now you are saying that if the day is between 1 and 7, it's invalid. The typo in the original would be 1 <= day_inp since any value 1 or greater would be invalid. To kick back the error if day selection is out of range it needs to be 1 > day_inp or 7 < day_inp. You can't use = in this case because that would mean 1 and 7 are also invalid.
Reply
#10
Thanks for all the help guys... I really appreciate it:-)

Another general problem
Quote:5. Sum all the elements in a list up to but not including the first even number.
(What if there is no even number?)
6. Count how many words occur in a list up to and including the first occurrence of the word “sam”.
(What if “sam” does not occur?)

This part of my code for exercise 5 works fine.

numbers = [-1,3,5,-9,7,12,13,15,6,19,22,23]
sum_5=0
for n in numbers:
    if n%2==0:
        break
    sum_5+=n
print ("The sum of the odd numbers up untill an even number is",sum_5)
However, how do I add an extra clause to include a "There are no even numbers" print message in case there are no even numbers in the list? I've tried numerous things , it just doesn't work for me.

I also understand that you probably just need to adapt the code from exercise 5, to complete 6. But how do I get Python to include the "n" after the break? I feel like it's something so simple, and I'll feel really stupid once I see the solution. But I just can't seem to figure it out.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Why doesn't calling a parent constructor work with arbitrary keyword arguments? PurposefulCoder 4 930 Jun-24-2023, 02:14 PM
Last Post: deanhystad
  Why doesn't this code work? What is wrong with path? Melcu54 7 1,778 Jan-29-2023, 06:24 PM
Last Post: Melcu54
  color code doesn't work harryvl 1 884 Dec-29-2022, 08:59 PM
Last Post: deanhystad
  How to use the LIKE clause in Python Columbo 9 1,620 Oct-09-2022, 10:22 PM
Last Post: Larz60+
  client.get_all_tickers() Doesn't work gerald 2 1,705 Jun-16-2022, 07:59 AM
Last Post: gerald
  pip doesn't work after Python upgrade Pavel_47 10 4,182 May-30-2022, 03:31 PM
Last Post: bowlofred
  For Loop Works Fine But Append For Pandas Doesn't Work knight2000 2 2,007 Dec-18-2021, 02:38 AM
Last Post: knight2000
  SQL Query is not executing WHERE clause hammer 7 2,323 Nov-15-2021, 01:44 PM
Last Post: hammer
  Class Method to Calculate Age Doesn't Work gdbengo 1 1,699 Oct-30-2021, 11:20 PM
Last Post: Yoriz
  Process doesn't work but Thread work ! mr_byte31 4 2,610 Oct-18-2021, 06:29 PM
Last Post: mr_byte31

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020