Multiple functions

Tags

So far, the programs we've seen have one function, mostly. You usually have several in one program. Let's see what that looks like.

I grew up in Australia in the 1960s. Yes, I'm old. Also ugly, smelly, and stupid. That comes with being old.

We inherited Britain's currency system. Instead of dollars and cents, we had pounds, shillings, and pence. Here they are, though not to scale.

Penny Shilling

Pound

There were twelve pennies to one shilling, and twenty shillings to one pound.

Shopping was a pain.

"That's 3 times 4s 8d, plus 2 times £1 16s 10d, plus 5 times 18s 8d... I'm too tired, I have to lie down."

Adela
Adela

You've got to be joking. This is a stupid system.

You're half right. It was a stupid system, but I'm not joking.

Not any more clunky than imperial units, though. How many feet in a mile again?

Adela
Adela

OK, fair point.

In 1966, we switched from the British system to dollars and cents. Yay! We went to metric in the 1970s. Ahhh, those nice powers of ten.

When you changed your money in 1966, you got two dollars for one pound. Easy enough, but what if you had £18 19s 11d? Umm...

Let's write a program to help. Not a great program, maybe, but it lets us talk about a program with several functions.

Here's some I/O.

  • Pounds? 3
  • Shillings? 13
  • Pence? 8
  • Dollars: 7.37

Here's one function:

  • def get_pounds():
  •     user_input = input('Pounds? ')
  •     # Test whether input was numeric.
  •     try:
  •         pounds = int(user_input)
  •     except ValueError:
  •         print('Sorry, you must enter a whole number.')
  •         sys.exit()
  •     # Test range.
  •     if pounds < 0 or pounds > 1000:
  •         print('Sorry, pounds should zero or more and 1,000 or less.')
  •         sys.exit()
  •     return pounds

Another:

  • def get_shillings():
  •     user_input = input('Shillings? ')
  •     # Test whether input was numeric.
  •     try:
  •         shillings = int(user_input)
  •     except ValueError:
  •         print('Sorry, you must enter a whole number.')
  •         sys.exit()
  •     # Test range.
  •     if shillings < 0 or shillings > 19:
  •         print('Sorry, shillings should be from 0 to 19.')
  •         sys.exit()
  •     return shillings

When there's a function, there's code that calls it. The calling code is often in a main program. The main program is where Python starts running your code. Then it calls the functions.

One question is: where do you put the main program's code? One option is to spread the code between the functions.

Spoiler

It's a bad idea.

Like this:

  • import sys
  •  
  • def get_pounds():
  •     user_input = input('Pounds? ')
  •     # Test whether input was numeric.
  •     try:
  •         pounds = int(user_input)
  •     except ValueError:
  •         print('Sorry, you must enter a whole number.')
  •         sys.exit()
  •     # Test range.
  •     if pounds < 0 or pounds > 1000:
  •         print('Sorry, pounds should zero or more and 1,000 or less.')
  •         sys.exit()
  •     return pounds
  •  
  • # Get the input
  • pounds = get_pounds()
  •  
  • def get_shillings():
  •     user_input = input('Shillings? ')
  •     # Test whether input was numeric.
  •     try:
  •         shillings = int(user_input)
  •     except ValueError:
  •         print('Sorry, you must enter a whole number.')
  •         sys.exit()
  •     # Test range.
  •     if shillings < 0 or shillings > 19:
  •         print('Sorry, shillings should be from 0 to 19.')
  •         sys.exit()
  •     return shillings
  •  
  • shillings = get_shillings()
  •  
  • def get_pence():
  •     user_input = input('Pence? ')
  •     # Test whether input was numeric.
  •     try:
  •         pence = int(user_input)
  •     except ValueError:
  •         print('Sorry, you must enter a whole number.')
  •         sys.exit()
  •     # Test range.
  •     if pence < 0 or pence > 11:
  •         print('Sorry, pence should be from 0 to 11.')
  •         sys.exit()
  •     return pence
  •  
  • pence = get_pence()
  •  
  • # Compute pounds as a decimal.
  • pounds = pounds + (shillings + pence/12)/20
  • # Convert to dollars.
  • dollars = pounds * 2
  • dollars = round(dollars, 2)
  • # Output
  • print('Dollars: ' + str(dollars))

What's the problem?

Georgina
Georgina

It's hard to find where the program starts. The first line to run is... pounds = get_pounds()? Maybe?

Right! The fact you're not sure is a problem.

Here's another way to arrange the code, that's more standard.

  • import sys
  •  
  • def get_pounds():
  •     user_input = input('Pounds? ')
  •     # Test whether input was numeric.
  •     try:
  •         pounds = int(user_input)
  •     except ValueError:
  •         print('Sorry, you must enter a whole number.')
  •         sys.exit()
  •     # Test range.
  •     if pounds < 0 or pounds > 1000:
  •         print('Sorry, pounds should zero or more and 1,000 or less.')
  •         sys.exit()
  •     return pounds
  •  
  • def get_shillings():
  •     user_input = input('Shillings? ')
  •     # Test whether input was numeric.
  •     try:
  •         shillings = int(user_input)
  •     except ValueError:
  •         print('Sorry, you must enter a whole number.')
  •         sys.exit()
  •     # Test range.
  •     if shillings < 0 or shillings > 19:
  •         print('Sorry, shillings should be from 0 to 19.')
  •         sys.exit()
  •     return shillings
  •  
  • def get_pence():
  •     user_input = input('Pence? ')
  •     # Test whether input was numeric.
  •     try:
  •         pence = int(user_input)
  •     except ValueError:
  •         print('Sorry, you must enter a whole number.')
  •         sys.exit()
  •     # Test range.
  •     if pence < 0 or pence > 11:
  •         print('Sorry, pence should be from 0 to 11.')
  •         sys.exit()
  •     return pence
  •  
  • # Get the input
  • pounds = get_pounds()
  • shillings = get_shillings()
  • pence = get_pence()
  • # Compute pounds as a decimal.
  • pounds = pounds + (shillings + pence/12)/20
  • # Convert to dollars.
  • dollars = pounds * 2
  • dollars = round(dollars, 2)
  • # Output
  • print('Dollars: ' + str(dollars))

All the functions come first. The main program is at the end. The first line to run is the first in the main program.

Ethan
Ethan

It's easier to tell what the main program does, too, when you can see it all at once.

Good point!

Ray
Ray

Hey, could we add a comment, showing where the main program starts?

Ooo, good idea, I didn't think of that.

  • def get_pence():
  •     user_input = input('Pence? ')
  •     # Test whether input was numeric.
  •     try:
  •         pence = int(user_input)
  •     except ValueError:
  •         print('Sorry, you must enter a whole number.')
  •         sys.exit()
  •     # Test range.
  •     if pence < 0 or pence > 11:
  •         print('Sorry, pence should be from 0 to 11.')
  •         sys.exit()
  •     return pence
  •  
  • # ====== Main program starts ======
  •  
  • # Get the input
  • pounds = get_pounds()
  • shillings = get_shillings()
  • pence = get_pence()

I like it! Yay for Ray!

Adela
Adela

Just to make sure I understand.

The program will run the same if the main program is scattered. The computer doesn't care.

But the code is harder to understand. It will take longer to change. Longer to debug, if you test it and there's a problem.

Business changes all the time, so programs change all the time. Programmer time is expensive, so the more programmer time we can save, the more efficient the IT operation is, and the lower the cost of running the business.

Yes! That's a great way to say it.

BTW, this is the sort of thing that'll make you stand out in a job interview. There could be a bunch of people with more tech expertise than you, but if they want to show how smart they are, rather than be productive... that's a problem.

For them. It's good for you.