Quitters

What we have

Our program asks users a question:

  • Service level (g=great, o=ok, s=sucked)?

They type something and press Enter.

If they don't type something valid, we want to show an error message, and keep asking.

  • Service level (g=great, o=ok, s=sucked)? Meh, ya know
  • Please enter G, O, or S.
  • Service level (g=great, o=ok, s=sucked)? I jes tole ya!
  • Please enter G, O, or S.
  • Service level (g=great, o=ok, s=sucked)? Passive aggressive much?
  • Please enter G, O, or S.
  • Service level (g=great, o=ok, s=sucked)? Ok, OK... O
  • Please enter G, O, or S.
  • Service level (g=great, o=ok, s=sucked)? O
  • -----------------

So something like:

  • while Input is not valid:
  •     Ask for input

We've got the same normalization issue from before.

Reflect

What's normalization mean here?

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Georgina
Georgina

Like, converting user input to one format. Remove extra spaces, lowercase.

Aye.

Reflect

Why does normalization help users?

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Ethan
Ethan

They don't have to worry about irrelevant differences in input, like "G", "g ", "G " and other things all work.

Right.

Reflect

Why does normalization make coding easier?

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Georgina
Georgina

Ooo! I know! ifs and whiles are easier to write. Instead of...

  • if service_level != 'G' && service_level != 'G ' && service_level != ' G ' && lots more

... we can write...

  • if service_level != 'g' and service_level != 'o' and service_level != 's':

We need to normalize service_level before this test, though.

Indeed!

Here's some pseudocode (code-ish, but easier to understand):

This is better:

  • Initialize input varaible
  • while Input is not valid:
  •     Ask user to input the service level
  •     Normalize input
  •     if input not valid:
  •         Show error message

Here's the code from last time.

  1. # Initialize service_level
  2. service_level = ''
  3. # Is the service level valid?
  4. while service_level != 'g' and service_level != 'o' and service_level != 's':
  5.     # Don't have a valid service level yet
  6.     # Ask user to input the service level
  7.     service_level = input('Service level (g=great, o=ok, s=sucked)? ')
  8.     # Normalize input
  9.     service_level = service_level.strip().lower()
  10.     # Is the service level valid?
  11.     if service_level != 'g' and service_level != 'o' and service_level != 's':
  12.         # Show error message
  13.         print('Please enter G, O, or S.')
Reflect

Why is line 2 there? The initialization thing.

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Adela
Adela

Line 4 uses a variable called service_level. If the variable doesn't exist yet, the program will crash. Line 2 creates the variable.

Bee tee dubs, we made the variable MT, so the while would work the first time. We could have...

  • service_level = 'burt is a good boi'

... or anything that isn't a valid value.

Good! And yes, Burt is a good boy.

Burt

My friend ​Burt

Let's make change the program, to make it more convenient for users.

So, we show the user the prompt:

  • Service level (g=great, o=ok, s=sucked)?

Say they wanted to stop the program. What would they do?

Ray
Ray

Maybe type quit?

Reflect

Does that work? Why?

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Ray
Ray

Well, poop. The program loops until it gets g, o, or s.

If you hit Ctrl+C once or twice, the program will throw an error and stop.

Reflect

Use Ctrl+C to stop the program in Spyder. What would your grandma think if she saw that message?

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Adela
Adela

Euww. We don't want to show users errors like that. Abuela would freak out.

Let's give the user a quit option...

  • Service level (g=great, o=ok, s=sucked, q=quit)? q
  • OK, bye!

Here's the code again:

  1. # Initialize service_level
  2. service_level = ''
  3. # Is the service level valid?
  4. while service_level != 'g' and service_level != 'o' and service_level != 's':
  5.     # Don't have a valid service level yet
  6.     # Ask user to input the service level
  7.     service_level = input('Service level (g=great, o=ok, s=sucked)? ')
  8.     # Normalize input
  9.     service_level = service_level.strip().lower()
  10.     # Is the service level valid?
  11.     if service_level != 'g' and service_level != 'o' and service_level != 's':
  12.         # Show error message
  13.         print('Please enter G, O, or S.')

We need to change a coupla things. First, we need to change the test on lines 4 and 11 so they accept q. Right now, it's...

  • service_level != 'g' and service_level != 'o' and service_level != 's'
Reflect

How would you change the test?

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Adela
Adela

I think it's...

  • service_level != 'g' and service_level != 'o' and service_level != 's' and service_level != 'q'

Aye!

Ethan
Ethan

Hey, that test is long, it's getting hard to fit it on a line. What should I do?

One way is to add \ to break up the line:

  • service_level != 'g' and service_level != 'o' \
  •     and service_level != 's' and service_level != 'q'

We'll see some other ways later.

OK, we're adding a quit option. We'll change the code, adding to the test:

  • service_level != 'g' and service_level != 'o' and service_level != 's' and service_level != 'q'
Reflect

What else do we need to change? Running the program and checking the I/O might help.

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Ethan
Ethan

Oh! We need to tell users about the option. Change the prompts!

Correct!

  • service_level = input('Service level (g=great, o=ok, s=sucked, q=quit)? ')
  • ...
  • print('Please enter G, O, S, or Q.')

Good! Here's the new code for the loop.

  1. # Initialize
  2. service_level = ''
  3. while service_level != 'g' and service_level != 'o' \
  4.     and service_level != 's' and service_level != 'q':
  5.     # Get user input
  6.     service_level = input(
  7.         'Service level (g=great, o=ok, s=sucked, q=quit)? '
  8.     )
  9.     # Normalize service level
  10.     service_level = service_level.strip().lower()
  11.     # Validate service level
  12.     if service_level != 'g' and service_level != 'o' \
  13.         and service_level != 's' and service_level != 'q':
  14.         print('Please enter G, O, S, or Q.')

That's it.

Lines 6 - 8 show another way to break up lines that are too long. Remember, input() is a function. You call a function like this:

  • function(arguments)

(Arguments are often called parameters. It's just a different name.)

You can line break with the args:

  • function(
  •     arguments
  • )

It's cleaner than a \, but in...

  • while service_level != 'g' and service_level != 'o' and service_level != 's' and service_level != 'q':

... there are no parens to break. So, we have to use \.

We wanted to add a new input option, so we:

  • Changed the if and while tests, so the new option would be valid.
  • Changed the prompts, to tell the user about the new option.
Reflect

Run the program with the new code. Does quit work? Why?

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Adela: Aha!
Adela

Why won't it... Aha!

We changed validation so q is acceptable, but the program doesn't do anything with it. We didn't tell the program to stop when the user types q.

Aye, that's right.

So, after the input is validated, let's add another if so the program exits if the user typed q.

Reflect

Try adding the if. What's the new code?

If you were logged in as a student, the lesson would pause here, and you'd be asked to type in a response. If you want to try that out, ask for an account on this site.
Georgina
Georgina

Yeehah! I dun got it, cowboys!

  • # Initialize
  • service_level = ''
  • while service_level != 'g' and service_level != 'o' \
  •     and service_level != 's' and service_level != 'q':
  •     # Get user input
  •     ...
  •  
  • # Check for exit.
  • if service_level == 'q':
  •     print('OK, bye!')
  •     sys.exit()
  •  
  • # Processing
  • if service_level == 'g':
  • ...

Good. So, to add a quit option, we:

  • In validation:
    • Changed the if and while tests, so the quit option would be valid.
    • Changed the prompts, to tell the user about the quit option.
  • After validation, added code to implement the new option.