Python Arena
Step 5 of 5

Parameters, not outside variables

So far, everything a function used came in through its parameters. But a function can also see the variables of the main program, the ones made outside every function. These are called global variables. Python lets a function use them, but it's a habit to avoid: it leads to bugs that hide well.

Here is one. This program first worked with a single temperature, kept in the variable temperature. Then the conversion from Celsius to Fahrenheit was moved into a function, but one name inside it was left as it was:

temperature = 25


def to_fahrenheit(celsius):
    fahrenheit = temperature * 9 / 5 + 32
    print(f"{celsius} C is {fahrenheit} F")


to_fahrenheit(0)
to_fahrenheit(100)
to_fahrenheit(25)
Output
0 C is 77.0 F
100 C is 77.0 F
25 C is 77.0 F

Water doesn't freeze at 77 degrees Fahrenheit, and it doesn't boil there either. The parameter celsius only makes it into the text: the calculation still uses temperature, the global variable, so every call converts 25 degrees. The last line is correct, but only by luck, because its argument happens to be the value of the global variable. Had the function been tried only with 25, it would have seemed to work.

Why it goes wrong

A function that uses only its parameters does the same work wherever it's called from: everything it needs comes in through the call. A function that reads a global variable depends on something outside it. When that variable changes, or doesn't exist, the function behaves differently, though nobody changed the function. Here is the same function in a program without the global variable:

def to_fahrenheit(celsius):
    fahrenheit = temperature * 9 / 5 + 32
    print(f"{celsius} C is {fahrenheit} F")


to_fahrenheit(100)
Python stops with
Traceback (most recent call last):
  File "main.py", line 6, in <module>
    to_fahrenheit(100)
    ~~~~~~~~~~~~~^^^^^
  File "main.py", line 2, in to_fahrenheit
    fahrenheit = temperature * 9 / 5 + 32
                 ^^^^^^^^^^^
NameError: name 'temperature' is not defined

This traceback has two parts: first the call on line 6, then line 2 inside to_fahrenheit, where the error happened. Read it from the bottom: the last lines show where the program stopped.

The checks on this site work like that second program. They load your program and call your function on its own, with their own arguments. If your function relies on a global variable, that variable may not exist when the checks call it, or it may hold a value that has nothing to do with their arguments.

Everything through parameters

So when a function needs a value, make it a parameter, and give the value as an argument in the call. Variables that the function makes for itself, such as total here, are fine: they belong to the function.

def price_with_tax(price, tax_percent):
    total = price + price * tax_percent // 100
    print(f"{price} with {tax_percent}% tax is {total}")


price_with_tax(100, 24)
price_with_tax(50, 10)
Output
100 with 24% tax is 124
50 with 10% tax is 55

Your task

Challenge 1 of 3

This function was tried in a program that happened to have a global variable count, so it seemed to work. Called on its own, it fails. Fix it so it uses only its parameters. A call order_summary("soup", 2) should print:

Order: 2 x soup
Kitchen, please make 2 portions.

Challenge 2

What does this program print? Type each line it prints.

Challenge 3

This function draws a box around a text, but it takes the text and the character from global variables. Change it so it takes them as parameters instead, in this order: box(text, character). A call box("Hi", "#") prints:

######
# Hi #
######