0

As my junior poroject i am coding a calculator in python with tkinter and i have a problem. If i understand correctly variable initialized in main body should be accesible in any function created after init of that variable. Thats why i dont understand why my code is giving me:

Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\przem\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "D:\Python\Projekty\tkinter_tutorial\calculator.py", line 36, in <lambda>
btn_2 = tk.Button(master=frm_numbers, text="2", command = lambda: click_btn('2'))
File "D:\Python\Projekty\tkinter_tutorial\calculator.py", line 8, in click_btn
print(first_number, type(first_number), first_number == 0)
UnboundLocalError: local variable 'first_number' referenced before assignment

My code:

import tkinter as tk

first_number = 0.0
second_number = 0.0

def click_btn(number):

    print(first_number, type(first_number), first_number == 0)
    if number in "0123456789":
        lbl_equation['text'] = lbl_equation['text'] + number
    elif number == '+':
        if first_number != 0.0 :
            first_number = float(lbl_equation['text'])
            lbl_equation['text'] = ""
            action = number
            print("pierwszy if %f"%first_number)
        else:
            second_number = float(lbl_equation['text'])
            lbl_equation['text'] = ""
            action = number
            print("Drugi if ", number)


window = tk.Tk()

frm_numbers = tk.Frame(master=window)
frm_numbers.grid(column=1, row=0, columnspan=3, sticky="w")

btn_1 = tk.Button(master=frm_numbers, text="1", command = lambda: click_btn('1'))
btn_2 = tk.Button(master=frm_numbers, text="2", command = lambda: click_btn('2'))
btn_3 = tk.Button(master=frm_numbers, text="3", command = lambda: click_btn('3'))
btn_4 = tk.Button(master=frm_numbers, text="4", command = lambda: click_btn('4'))
btn_5 = tk.Button(master=frm_numbers, text="5", command = lambda: click_btn('5'))
btn_6 = tk.Button(master=frm_numbers, text="6", command = lambda: click_btn('6'))
btn_7 = tk.Button(master=frm_numbers, text="7", command = lambda: click_btn('7'))
btn_8 = tk.Button(master=frm_numbers, text="8", command = lambda: click_btn('8'))
btn_9 = tk.Button(master=frm_numbers, text="9", command = lambda: click_btn('9'))
btn_0 = tk.Button(master=frm_numbers, text="0", command = lambda: click_btn('0'))

btn_plus = tk.Button(master=frm_numbers, text="+", command = lambda: click_btn('+'))
btn_minus = tk.Button(master=frm_numbers, text="-", command = lambda: click_btn('-'))
btn_multiple = tk.Button(master=frm_numbers, text="*", command = lambda: click_btn('*'))
btn_divide = tk.Button(master=frm_numbers, text="/", command = lambda: click_btn('/'))
btn_equal = tk.Button(master=frm_numbers, text='=', command = lambda: click_btn('='))

btn_1.grid(row=3, column=2)
btn_2.grid(row=3, column=3)
btn_3.grid(row=3, column=4)
btn_4.grid(row=2, column=2)
btn_5.grid(row=2, column=3)
btn_6.grid(row=2, column=4)
btn_7.grid(row=1, column=2)
btn_8.grid(row=1, column=3)
btn_9.grid(row=1, column=4)
btn_0.grid(row=4, column=3, columnspan = 3, sticky="ew")

btn_plus.grid(row=3, column=0)
btn_minus.grid(row=3, column=1)
btn_multiple.grid(row=2, column=0)
btn_divide.grid(row=2, column=1)
btn_equal.grid(row=4, column=0, columnspan=2, sticky="ew")

lbl_equation = tk.Label(master=frm_numbers, text="")
lbl_equation.grid(row=0, column = 2, columnspan = 3, sticky="ew")



window.mainloop()

What am i doing wrong/don't understand?

pluniewski
  • 11
  • 1
  • Because `first_number` is assigned to in the scope of the function, and you don't say it's a global name, the name is not resolved as being global. If you didn't assign to it, Python would know it was global. – Peter Wood May 30 '22 at 09:47
  • So i should use global keyword when i am addresing want-to-be global variable withing the function. Am i right? Because as far as i understand function creates now new variable within itself. – pluniewski May 30 '22 at 10:28
  • Yes you should use `global`. However, it doesn't get as far as creating the new name so it never happens. If you got rid of the condition using the name (which fails), then yes it would create a local new name rather than assign to the global name. – Peter Wood May 30 '22 at 20:21

0 Answers0