'I am new in python and self learner. A little kindness and support means lot to me to encourage me. percentage of my calculator does not work
I cannot able to solve the proper percentage function to properly work on my calculator. Please help.
this kind of error I get each time I run the percentage button
File "f:\Visial Studio\Calculator.py", line 53, in <lambda>
Button(root,text="%", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show(percentage)).place(x=290,y=100)
File "f:\Visial Studio\Calculator.py", line 19, in show
equation+=value
TypeError: can only concatenate str (not "function") to str
PS F:\Visial Studio> &
C:/Users/*******/AppData/Local/Microsoft/WindowsApps/python3.10.exe "f:/Visial
Studio/Calculator.py"
File "f:\Visial Studio\Calculator.py", line 28
equation=(value*value)/100)) #(a*b)/100
#===========Code===============================
import tkinter
from tkinter import *
from unittest import result
import math
root=Tk()
root.title("Basic Calculator")
root.geometry("570x600+100+200")
root. resizable(False,False)
root.configure(bg="#17161b")
#===========Formula===============================
equation=""
def show(value):
global equation
equation+=value
label_result.config(text=equation)
def clear():
global equation
equation=""
label_result.config(text=equation)
this is the place where I found the issues
def percentage():
global equation
equation=(value*value)/100)) #(a*b)/100
def calculate():
global equation
result=""
if equation !="":
try:
result=eval(equation)
except:
result="error"
equation=""
label_result.config(text=result)
#==========Label======================================================
label_result= Label(root,width=25,height=2,text="",font=("arial",30))
label_result.pack()
#==========Buttons======================================================
Button(root,text="C", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#3697f5",command=lambda: clear()).place(x=10,y=100)
Button(root,text="/", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("/")).place(x=150,y=100)
Button(root,text="%", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show(percentage)).place(x=290,y=100)
Button(root,text="x", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("*")).place(x=430,y=100)
Button(root,text="7", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("7")).place(x=10,y=200)
Button(root,text="8", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("8")).place(x=150,y=200)
Button(root,text="9", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("9")).place(x=290,y=200)
Button(root,text="-", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("-")).place(x=430,y=200)
Button(root,text="4", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("4")).place(x=10,y=300)
Button(root,text="5", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("5")).place(x=150,y=300)
Button(root,text="6", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("6")).place(x=290,y=300)
Button(root,text="+", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("+")).place(x=430,y=300)
Button(root,text="1", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("1")).place(x=10,y=400)
Button(root,text="2", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("2")).place(x=150,y=400)
Button(root,text="3", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("3")).place(x=290,y=400)
Button(root,text="0", width=11, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show("0")).place(x=10,y=500)
Button(root,text=".", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show(".")).place(x=290,y=500)
Button(root,text="=", width=5, height=3, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#fe9037",command=lambda: calculate()).place(x=430,y=400)
root.mainloop()
Solution 1:[1]
The problem is in this line of your code -:
Button(root,text="%", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show(percentage)).place(x=290,y=100)
The show function you call, concatenates the given argument to the string named equation. But, if the given argument is not a string, then the concatenation is not possible.
In this line the argument passed, is a function, i.e. the percentage function you previously defined, it thus, is not able to concatenate a function with a string, so it throws an error indicating that.
TypeError: can only concatenate str (not "function") to str
If what is intended, is to append the value returned by the percentage function, than all you have to do is call the percentage function using another set of round brackets and then convert the return value to a string using the str function and pass it into show like so -:
Button(root,text="%", width=5, height=1, font=("arial",30,"bold"),
bd=1,fg="#fff",bg="#2a2d36",command=lambda: show(str(percentage()))).place(x=290,y=100)
But, also note that it seems like the percentage function is not properly designed, as it is changing the value of the global variable equation to integer(int) type instead. While, for all other functions the value of equation is a string, which it technically is supposed to be, as you are using the value of equation as the label text.
EDIT: Also as mentioned by @acw1668, there were two extra round brackets at the end of the line that sets the value of the variable equation, that would have thrown an error, removing it is also part of redesigning the percentage function.
Redesigning the percentage function further to account for the above changes like so -:
def percentage():
global equation
return (value*value)/100 #(a*b)/100 #RETURN THE INT VALUE INSTEAD TO BE CONVERTED INTO STRING IN THE LAMBDA CALL FROM ABOVE.
should fix the problem.
NOTE: Also note, it seems like many of your functions may need redesigning similar to percentage function, as you are updating the value of equation string in the show function as well as in all the other functions you are calling(atleast those provided in the OP).
Also, I would suggest having a look at this, which is a better way to define widgets, than to place them in the same line where the constructor is called, eventhough here no reference is being saved of the object, but the current way of dealing with widgets can lead to an Attribute Error in some cases.
Further, dealing with global variables can sometimes be a little tricky, and/or might not give the results as required, so it is suggested to put such functions that relate to each other within a class and make use of a class's inner attributes using self. It would also allow you to make multiple instances of the same class, which would not work with normally defined functions that modify global variables.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
