M14) Shipping label traceback
A parcel service charges shipping per kilogram. Parcels within the Netherlands ("NL") cost 120 cents per kilogram, parcels to other EU countries ("EU") cost 250 cents, and all other destinations cost 400 cents. The program in Listing 1, saved as shipping.py, prints the text for a shipping label.
def rate_per_kg(zone: str) -> int:
if zone == "NL":
return 120
elif zone == "EU":
return 250
elif zone == "World":
return 400
def shipping_cost(weight: int, zone: str) -> int:
return weight * rate_per_kg(zone)
def label_text(weight: int, zone: str) -> str:
cost = shipping_cost(weight, zone)
return f"{zone}: {cost} cents"
print(label_text(2, "UK"))Running the program produces the traceback in Listing 2.
Traceback (most recent call last):
File "shipping.py", line 19, in <module>
print(label_text(2, "UK"))
^^^^^^^^^^^^^^^^^^^
File "shipping.py", line 15, in label_text
cost = shipping_cost(weight, zone)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "shipping.py", line 11, in shipping_cost
return weight * rate_per_kg(zone)
~~~~~~~^~~~~~~~~~~~~~~~~~~
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'Where is the defect, and why?
- In
rate_per_kg. Its last branch testszone == "World", so any other destination reaches the end of the function, which returnsNone. - On line 11 of
shipping_cost. Python cannot multiply a number by a function call, so the rate must be stored in a variable first. - On line 19.
"UK"is not a valid zone, so the call must pass"World"or"EU"instead. - In
shipping_cost. It must catch theTypeErrorwithtry-exceptand return 0.