Hours and Minutes math in a work week calculator
It's a nice little program. Intuitively I'd prefer to input the times as 1:30 instead of 1.5, but that's just a personal preference.

The self.hours_worked field is redundant. It should simply be a local variable in the hours_left_update method. It's kind of weird that you reset it at the end of the method instead of initializing it at the beginning of the method. Anyway, just make it a local variable.

I played around a bit and came up with this code:

def hours_left_update(self):
    minutes_worked = 0
    for entry in self.entry_list:
        if entry.get() != "":
            try:
                minutes_worked += 60 * float(entry.get())
            except:
                pass

    minutes_worked = round(minutes_worked)   # just in case
    minutes_left = 40 * 60 - minutes_worked

    self.lbl8.config(text="{:02d}h {:02d}m".format(minutes_worked // 60, minutes_worked % 60))
    self.lbl10.config(text="{:02d}h {:02d}m".format(minutes_left // 60, minutes_left % 60))


Is there any reason for waiting 500 ms before updating the total times after each key press? I generally don't expect programs to have unnecessary delays.

I changed the output format for the two computed fields. As a result, the format changes after I press the first key because the labels are initialized with the old format. To make things consistent, I'd create the labels without any text and call self.hours_left_update() at the end of the constructor.



After cleaning up the rest of the code, it looks like this:

from time import strftime
import tkinter as tk
import datetime


class TimeClockApp(tk.Frame):
    def __init__(self, master, *args, **kwargs):
        tk.Frame.__init__(self, master, *args, **kwargs)

        self.now_lbl = tk.Label(master)
        self.now_lbl.grid(row=0, column=0, columnspan=2)

        tk.Label(master, text="Hours worked").grid(row=1, column=0, columnspan=2)

        self.entries = []
        weekdays = ["Monday: ", "Tuesday: ", "Wednesday: ", "Thursday: ", "Friday: "]
        for i in range(5):
            tk.Label(master, text=weekdays[i], anchor="e").grid(row=i+2, column=0, sticky="e")
            entry = tk.Entry(master, width=7)
            entry.grid(row=i+2, column=1, sticky="w")
            entry.bind("&lt;Key&gt;", lambda event: master.after(0, self.update_totals))
            self.entries.append(entry)

        tk.Label(master, text="Total Hours worked:").grid(row=7, column=0, sticky="e")
        self.time_worked_lbl = tk.Label(master)
        self.time_worked_lbl.grid(row=7, column=1, sticky="w")

        tk.Label(master, text="Hours left to 40:").grid(row=8, column=0, sticky="e")
        self.time_left_lbl = tk.Label(master)
        self.time_left_lbl.grid(row=8, column=1, sticky="w")

        self.update_clock()
        self.update_totals()

    def update_clock(self):
        now = "Current Date-Time: {} ~ {}".format(datetime.date.today(), strftime("%H:%M:%S"))
        self.now_lbl.config(text=now)
        self.now_lbl.after(200, self.update_clock)

    def update_totals(self):
        minutes_worked = 0
        for entry in self.entries:
            try:
                minutes_worked += 60 * float(entry.get())
            except:
                pass

        minutes_worked = round(minutes_worked)
        minutes_left = 40 * 60 - minutes_worked

        self.time_worked_lbl.config(text="{:02d}h {:02d}m".format(minutes_worked // 60, minutes_worked % 60))
        self.time_left_lbl.config(text="{:02d}h {:02d}m".format(minutes_left // 60, minutes_left % 60))

if __name__ == "__main__":
    root = tk.Tk()
    app = TimeClockApp(root)
    root.mainloop()


I did at least the following:


Start the method names with a verb.
Rename lbl8 to time_worked_lbl, and similar ones.
Only store those labels in self that are needed by the other methods.
Replace self.master with a simple master.
Made the formatting consisten, especially the spacing around named arguments.
Removed unnecessary lambdas.
Merge the two for loops into one.
Build the UI elements strictly from top to bottom.


Too bad that the grid method doesn't return self. That would have saved some more lines. :) By the way, this means that your code did something unexpected. It stored None into self.lbl1.