All 50 exercises in “Practice Makes Python” are complete! (Plus, a sample exercise about taxes in Freedonia)

The latest draft of “Practice Makes Python,” my ebook intended to sharpen your Python programming skills, is now out. This draft includes all 50 exercises, solutions, and explanations that I had hoped to include in the book.

I’m very excited to have reached this milestone, and appreciate the input from my many students and colleagues who have provided feedback.

The next steps in my release of the book are: Use a different toolchain that will allow for internal hyperlinks in the PDF, generate epub and mobi formats, and then start on the video explanations that will be included in a higher-tier version of the book package. Even without these steps, the content of the book is ready, and is a great way for you to improve your Python skills. The book is not meant to teach you Python, and assumes that you are familiar with the basics.

Please check out the latest version of Practice Makes Python. In case you’re not sure whether the book is for you, I am enclosing another sample exercise, this time from the chapter on modules and packages. As always, comments and suggestions are welcome.

Sales tax

The Republic of Freedonia has a strange tax system. To help businesses calculate their sales taxes, the government has decided to provide a Python software library.

Sales tax on a purchase depends on where the purchase was made, as well as the time of the purchase. Freedonia has four provinces, each of which charges a different percentage of tax:

  • Chico: 50%
  • Groucho: 70%
  • Harpo: 50%
  • Zeppo: 40%

Yes, the taxes are quite high in Freedonia. (So high, in fact, that they are said to have a Marxist government.) However, these taxes rarely apply in full. That’s because the amount of tax applied depends on the hour at which the purchase makes place. The tax percentage is always multiplied by the hour at which the purchase was made. At midnight, there is no sales tax. From 12 noon until 1 p.m., only 50% (12/24) of the tax applies. And from 11 p.m. until midnight, 95% (i.e., 23/24) of the tax applies.

Your job is to implement that Python module, “freedonia.py”. It should provide a function, “calculate_tax”, which takes three arguments: The amount of the purchase, the province in which the purchase took place, and the hour (using 24-hour notation) at which it happened. The “calculate_tax” function should return the final price.

Thus, if I were to invoke

calculate_tax(500, 'Harpo', 12)

A $500 purchase in Harpo province (with 50% tax) would normally be $750. However, because the purchase was done at 12 noon, the tax is only half of its usual amount, or $125, for a total of $625. If the purchase were made at 9 p.m. (i.e, 21:00 on a 24-hour clock), then the tax would be 87.5% of its full rate, or 43.75%, for a total price of $718.75.

Note that while you can still use a single file, exercises such as this one lend themselves to having two files, one of which (“use_freedonia.py”) imports and then uses “freedonia.py”.

Solution

# freedonia.py
rates = {
 'Chico': 0.5,
 'Groucho': 0.7,
 'Harpo': 0.5,
 'Zeppo': 0.4
}

def time_percentage(hour):
    return hour / 24.0

def calculate_tax(amount, state, hour):
    return amount + (amount * rates[state] * time_percentage(hour))

And now, the program that uses it:

from freedonia import calculate_tax

print "You owe a total of: {}".format(calculate_tax(100, 'Harpo', 12))

print "You owe a total of: {}".format(calculate_tax(100, 'Harpo', 21))

Discussion

The “freedonia” module does precisely what a Python module should do: Namely, it defines data structures and functions that provide functionality to one or more other programs. By providing this layer of abstraction, it allows a programmer to focus on what is important to him or her, such as the implementation of an online store, without having to worry about the nitty-gritty of particular details.

While some countries have extremely simple systems for calculating sales tax, others — such as the United States — have many overlapping jurisdictions, each of which applies its own sales tax, often at different rates and on different types of goods. Thus, while the Freedonia example is somewhat contrived, it is not unusual to purchase or use libraries of this sort of sales taxes.

Our module defines a dictionary (“rates”), in which the keys are the provinces of Freedonia, and the values are the taxation rates that should be applied there. Thus, we can find out the rate of taxation in Groucho province with “rates[‘Groucho’]”. Or we can ask the user to enter a province name in the “province” variable, and then get “rates[province]”. Either way, that will give us a floating-point number which we can use to calculate the tax.

A wrinkle in the calculation of Freedonian taxation is the fact that taxes get progressively higher as the day goes on. In order to make this calculation easier, I wrote a “time_percentage” function, which simply takes the hour and returns it as a percentage of 24 hours. In Python 2, integer division always returns an integer, even when that means throwing away the remainder. Thus, we divide the current hour not by “24” (an int) but by “24.0” (a float), which ensures that the result will be a floating-point number.

Finally, the “calculate_tax” function takes three parameters — the amount of the sale, the name of the province in which the sale is taking place, and the hour at which the sale happened — and returns a floating-point number indicating the actual, current tax rate.

It should be noted that if you’re actually doing calculations involving serious money, you should almost certainly *not* be using floats. Rather, you should use integers, and then calculate everything in terms of cents, rather than dollars. This avoids the fact that floating-point numbers are not completely accurate on computers. (Try to add “0.1” and “0.7” in Python, and see what the result is.) However, for the purposes of this example, and given the current state of the Freedonian economy in any event, this is an acceptable risk for us to take.

Leave a Reply

Your email address will not be published. Required fields are marked *

76 − = sixty seven