my first python

Decided to write a simple, stand-alone calculator. In Python.
Uses Tkinter for platform-independent (Tk-based) GUI and re module for regular expressions.
Tried to be reasonably Pythony about it, using tuples and lists and dictionaries etc. as (I think) is typical.
The worst parts were trying to remember regex syntax and formatting syntax; nothing really to do with Python itself. Just rusty on those bits because I don't use them much these days.

The code:
from Tkinter import *
import re

class Calculator(Frame):

    # dict of buttons
    buttons = {}

    # track if need to clear display before updating display
    to_clear = True

    def createWidgets(self):
        options = {'width':10, 'textvariable':'self.display', 'bd':1, 'relief':GROOVE, 'anchor':E}
        self.label = Label(self, options)
        self.label.grid(row=0, column=0, columnspan=4, sticky=W+E)
        
        # labels for calculator buttons
        b_text =  ["/"] + range(9, 6, -1) 
        b_text += ["*"] + range(6, 3, -1)
        b_text += ["-"] + range(3, 0, -1) + ["+", "=", ".", 0] 

        # lay the buttons out, making the key layout coords, value a button widget
        for row in range(4, 0, -1):
            for column in range(4):
                self.buttons[(column, row)] = Button(self, text = b_text.pop())
                self.buttons[(column, row)].grid(row = row, column = column)
                self.buttons[(column, row)].bind('', self.button_click)

    def __init__(self, master):
        Frame.__init__(self, master)
        self.pack()

        # to keep the display dynamically updated
        self.display = StringVar()

        # initialize to something purty
        self.display.set("0.0")

        # set me up!
        self.createWidgets()

    # callback when button is click'd
    def button_click(self, event):
        wut = event.widget['text']

        if wut == '=': # calc it!
            eval_me = self.display.get()
            
            # if there are no decimals, convert the first number to a float
            # this forces floating-point maths
            if not '.' in self.display.get():
                # find the first group of digits, stick a '.0' on the end of it!
                eval_me = re.sub(r'(\d+)', r'\1.0', self.display.get(), count=1)

            result = '{: f}'.format(eval(eval_me))
            self.display.set(str(result).rstrip('0').rstrip('.'))
            self.to_clear = True

        else: # track the input

            # keep using result if you want to
            if wut in ["+", "-", ".", "/", "*"]:
                self.to_clear = False
                
            if  self.to_clear:
                self.display.set(wut)
                self.to_clear = False
                
            else: #keep using the result value displayed
                show_me = self.display.get() + str(wut)
                self.display.set(show_me)

# begin!
root = Tk()
calculator = Calculator(root)
calculator.mainloop()
root.destroy()

No comments: