Tracking hours worked for the days of the week

I am working through a udemy course on Python, this is the first real program I've written. I am new to Python and to programming.

I'd like to replace the main function below with something more efficient and less repetitive but I'm not sure what or how. The most I could think to do is write a function for adding hours and call it under each day.

Most relevant code:

def main(day):

if day == "Monday":
print "Today is %s, How many hours would you like to add today?" % (day)
hours = int(raw_input())
DOTW['Monday'] = DOTW['Monday'] + hours
print "Cool your hours for %s are %d" %(day, DOTW['Monday'])
want = raw_input("Do you want to add more time? y/n \n > ")
overtime()
leave(want)

if day == "Tuesday":
print "Ah, Today is %s, How many hours have you worked?" %(day)
hours = int(raw_input())
DOTW['Tuesday'] = DOTW['Tuesday'] + hours
print "alright, yours hours for %s are %d" %(day, DOTW['Tuesday'])
want = raw_input("Do you want to add more time? y/n \n > ")
overtime()
leave(want)

if day == "Wednesday":
print "Ah, Today is %s, How many hours have you worked?" %(day)
hours = int(raw_input())
DOTW['Wednesday'] = DOTW['Wednesday'] + hours
print "Cool for %s I've got %d hours" %(day, DOTW['Wednesday'])
want = raw_input("Do you want to add more time? y/n \n > ")
overtime()
leave(want)

if day == "Thursday":
print "Ah, Today is %s, How many hours have you worked?" %(day)
hours = int(raw_input())
DOTW['Thursday'] = DOTW['Thursday'] + hours
print "Your hours for %s are %d" %(day, DOTW['Thursday'])
want = raw_input("Do you want to add more time? y/n \n > ")
overtime()
leave(want)

if day == "Friday":
print "FINALLY IT'S FRIDAY!!! How many hours have you worked?"
hours = int(raw_input())
DOTW['Friday'] = DOTW['Firday'] + hours
print "Cool. for %s I've got %d hours" %(day, DOTW['Friday'])
want = raw_input("Do you want to add more time? y/n \n > ")
overtime()
leave(want)

if day == "Saturday":
print "Ah, Today is %s, How many hours have you worked?" %(day)
hours = int(raw_input())
DOTW['Saturday'] = DOTW['Saturday'] + hours
print "alright, yours hours for %s are %d" %(day, DOTW['Saturday'])
want = raw_input("Do you want to add more time? y/n \n > ")
overtime()
leave(want)

if day =="Sunday":
print "Ah, Today is %s, How many hours have you worked?" %(day)
hours = int(raw_input())
DOTW['Sunday'] = DOTW['Sunday'] + hours
print "Cool your hours for %s are %d" %(day, DOTW['Monday'])
want = raw_input("Do you want to add more time? y/n \n > ")
overtime()
leave(want)


The entire program: http://pastebin.com/8hLVcGMr

• You might as well include the rest of the code. It's just a little bit more, and the question would make sense on its own. – 200_success Nov 30 '15 at 9:19

2 Answers

The first step to reducing repetition is to use variables instead of literals. Why call DOTW['Monday'] when you could just use day as your key. Importantly, this will avoid errors like the one you created in the Sunday block, where you actually display Monday's hours instead of Sunday's.

The only difference between days is in the messages that you print to the user. You've given custom messages, but you could just put those in a dictionary and access them the same way you access DOTW. Here's an example of how the greeting could look:

today_messages = {
"Monday": "Today is %s, How many hours would you like to add today?",
"Tuesday": "Ah, Today is %s, How many hours have you worked?",
"Wednesday": "Ah, Today is %s, How many hours have you worked?",
"Thursday": "Ah, Today is %s, How many hours have you worked?",
"Friday": "FINALLY IT'S FRIDAY!!! How many hours have you worked?",
"Saturday": "Ah, Today is %s, How many hours have you worked?",
"Sunday": "Ah, Today is %s, How many hours have you worked?",
}


With those changes you could make it all one block with just one test because Friday's message is an exception that doesn't need the string formatting argument.

def main(day):
if day == "Friday":
print today_messages[day]
else:
print today_messages[day] % day

hours = int(raw_input())
DOTW[day] = DOTW[day] + hours
print hours_worked[day] %(day, DOTW[day])
want = raw_input("Do you want to add more time? y/n \n > ")
overtime()
leave(want)


Also you should use the newer str.format method. Using % is the old way, and str.format has a lot of useful formatting options. You don't particularly need them in your case but it's clearer and cleaner syntax. The basic way to use it is like this:

                "Sunday": "Ah, Today is {}, How many hours have you worked?",

...

print today_messages[day].format(day)


The particular advantage for you here is that formatting a message that takes no arguments won't raise errors, unlike with %.

>>> string = "Ignore me"
>>> "Hello World!" % string

Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
"Hello World!" % string
TypeError: not all arguments converted during string formatting
>>> "Hello World!".format(string)
'Hello World!'


This means you no longer need to test for "Friday", since the format call will just be ignore for that string:

def main(day):
print today_messages[day].format(day)
hours = int(raw_input())
DOTW[day] = DOTW[day] + hours
print hours_worked[day].format(day, DOTW[day])

want = raw_input("Do you want to add more time? y/n \n > ")
overtime()
leave(want)

1. You are adding all of the values, so sum the values instead:

hoursWorked = DOTW['Monday'] + DOTW['Tuesday'] + DOTW['Wednesday'] + ...

hoursWorked = sum(DOTW.values())

2. PaycheckCalculator is not called anywhere, maybe you forgot to call it? Also pascal-case is recommended for naming classes, not functions. paycheck_calculator would be more appropriate.

3. Assignment can be combined with arithmetic operation:

DOTW[day] = DOTW[day] + hours

DOTW[day] += hours