Kicking off your learning

Day 3 Project: A Simple Earnings Calculator

Welcome to the first mini project in the 30 Days of Python series. For this project we're going to be creating a simple console application that will help an employer calculate an employee's earning in a given week.

If you haven't tackled the rest of the day 3 content, I'd recommend you do that before trying the project.

Below you'll find a project brief, as well as a model solution with an explanation. I'd really recommend you give this a go on your own before looking at the solution; you'll get a lot more out of it, I promise. If you get stuck, there's nothing wrong with referring back to the previous posts in this series, or looking at any notes you've written. This isn't an exam!

Once you've written your program, you shouldn't be worried if it looks a little bit different to ours. You might have chosen different variable names or prompts, or you might have used a slightly different approach to us. This is absolutely fine. There are often may different ways to write even very short programs like this.

The brief

Our application should work as follows:

  1. The user should be given three prompts where they'll be asked to provide different information about an employee. One prompt should ask for the employee's name, another should ask for their hourly wage, and the final one should ask how many hours the employee worked this week.
  2. The employee name should be processed to ensure that it's in a particular format. All employee names should be stripped of any excess white space, and should be in title case. This means that each word is capitalised with all other letters being lowercase. For example, if the employer accidentally has caps lock on and they write "rEGINA gEORGE", the name will still be correctly stored as "Regina George".
  3. The employee's total earnings for the week should be calculated by multiplying the hours worked by their hourly wage.
  4. Remember that any user input we receive is going to be a string. While we can multiply strings, it won't quite do what you want in this case. It's also worth keeping in mind that the employee's wage, or the numbers of hours they worked, might not be a whole number.
  5. After processing the employee's name and calculating their earnings for the week, the program should output this information as a single string. For example, output like this would be appropriate:
Regina George earned $800 this week.

Solution walkthrough

Below you'll find a walkthrough for how we would approach this particular problem. Once again, if yours is a little different, don't worry!

For this project, we're just going to tackle things one step at a time. It's always a good idea to break down tasks into simple chunks, because it makes projects way less intimidating.

First up, we're just going to ask the user for some information. We're not going to process any of the strings, and we're not going to worry about types. We just want to get information from the user and store this information in some variables.

name = input("Please enter the employee's name: ")
hourly_wage = input("What is their hourly wage? ")
hours_worked = input("How many hours have they worked this week? ")

If we want to test that things work, we can just print the variables:

print(name)
print(hourly_wage)
print(hours_worked)

We shouldn't have any problems at this stage, so we can move onto correcting the name input. There are a few options for how we write this, but fundamentally the approaches are going to be the same. We need to call the strip method to remove excess white space from both ends of the string, and we need to call title to convert the string to title case.

One way we could do this is to create three different variables, and perform a different operation on each line:

name = input("Please enter the employee's name: ")
stripped_name = name.strip()
title_name = stripped_name.title()

This is fine, but we don't need to use different variable names here. We're not going to use the name in its raw form, so we don't need to preserve it. The same for the string we've stripped of white space. We're only concerned with the final product, so we can safely overwrite name at each stage:

name = input("Please enter the employee's name: ")
name = name.strip()
name = name.title()

If we want to be really succinct, we can chain various operations on the end of the input call like this:

name = input("Please enter the employee's name: ").strip().title()

The reason this works, is because Python is going to evaluates each of these calls (which are all expressions) one at a time, starting from the left.

So first we have the input call. This is going to evaluate to a string before strip is called.

Let's imagine the user enters " rEGINA gEORGE ", with all this white space around the actual name. This is what we get back from input, so after input has finished running, our line of code is roughly equivalent to this:

name = " rEGINA gEORGE  ".strip().title()

Now the next operation to perform is the strip call. strip also evaluates to a new string, so we end up with something like this:

name = "rEGINA gEORGE".title()

Now the white space is gone, and we have one more operation to perform: the call the title. title, much like strip and input, evaluates to another string, which leaves us with this:

name = "Regina George"

Now that our employee's name has been properly processed we can start thinking about calculating their earnings. Unfortunately, we're not going to be able to do this:

name = input("Please enter the employee's name: ").strip().title()
hourly_wage = input("What is their hourly wage? ")
hours_worked = input("How many hours have they worked this week? ")

earnings = hourly_wage * hours_worked

This is going to give us a TypeError:

Traceback (most recent call last):
    File "main.py", line 5, in <module>
    earnings = hourly_wage * hours_worked
TypeError: can't multiply sequence by non-int of type 'str'

The message here is fairly clear, we're multiply a string by a string, but at least one of these needs to be an integer.

Okay, so let's change the hours worked to an integer and see what happens:

name = input("Please enter the employee's name: ").strip().title()
hourly_wage = input("What is their hourly wage? ")
hours_worked = input("How many hours have they worked this week? ")

earnings = hourly_wage * int(hours_worked)

print(earnings)

If you try to run this code, you're going to get the value you entered for the hourly wage repeated a number of times equal to the value you entered for hours worked. This is because multiplying strings by an integer is a shorthand for performing a repeated string concatenation. "-" * 5 is the same as "-" + "-" + "-" + "-" + "-".

With this in mind, we're going to need to convert both values to numbers. However, instead converting to integers, we're going to convert to floats, because this will allow us to accept non-integral values for the user's wage or hours worked. We want to be able to calculate 32.5 hours worked at an hourly wage of 13.50, for example.

name = input("Please enter the employee's name: ").strip().title()
hourly_wage = input("What is their hourly wage? ")
hours_worked = input("How many hours have they worked this week? ")

earnings = float(hourly_wage) * float(hours_worked)

Make sure you print earning to check your code. If Python raises some exceptions, try to figure out why they're happening using the error message and the traceback.

One thing we won't be able to do is accept a wage with a currency symbol. If you want an extra challenge, you can try to figure out how to do this for your local currency. You might want to look at the documentation for strip, lstrip, and rstrip.

Now that we've written all of our program's logic, we just need to output the information to the user. I'm going to use an f-string here, but you're more than welcome to use format or string concatenation if you prefer. If you use concatenation, remember that you can only concatenate strings!

name = input("Please enter the employee's name: ").strip().title()
hourly_wage = input("What is their hourly wage? ")
hours_worked = input("How many hours have they worked this week? ")

earnings = float(hourly_wage) * float(hours_worked)

print(f"{name} earned ${earnings} this week.")

With that we're done!

Hopefully you were able to do this on your own, but if not, don't worry! Programming is hard, and it takes time to really absorb these new concepts. Stick with it, and make sure to review the content for the last few days if you need to.

As always, you can find us on Discord if you need any help.

Bonus material

One tiny issue you may notice is that we have a variable amount of precision after the decimal point when printing the employee's earnings. There are several ways we can get around this, a few of which you can find below if you're interested in digging into this a bit deeper.

One option is to convert the result of our calculation to an integer. This will "truncate" the float, essentially throwing away everything after the decimal point. This certainly looks a lot better, but we're throwing away some precision.

A slightly better option is to round the float, rather than just trimming off the values after the decimal point. There are some subtleties you need to be aware of when rounding in Python, but we have a post you can read on this topic.

A final solution to this problem involves using some a special formatting language which comes as part of Python. One of its feature will allow us to specify how many decimal places we want to display for our floats. We have a post on this topic as well.

Here is what our solution would look like using these special formatting options:

name = input("Please enter the employee's name: ").strip().title()
hourly_wage = input("What is their hourly wage? ")
hours_worked = input("How many hours have they worked this week? ")

earnings = float(hourly_wage) * float(hours_worked)

print(f"{name} earned ${earnings:.2f} this week.")