파이썬 실전 프로젝트

계산기 만들기-2 : 함수구현

앞서 만든 계산기에 함수를 추가해서 계산이 가능하도록 하겠습니다.

각 버튼별 함수 만들기

함수는 총 3개입니다. (숫자입력 및 AC버튼(지우기) 처리함수, 사칙연산 처리함수, 이퀄버튼 처리함수)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
from tkinter import *
from tkinter import ttk
operation = '' #연산자 저장 변수
temp_number = 0 #이전값 저장 변수
# 숫자버튼 처리 함수
def button_pressed(value):
# 입력값이 'AC'일때
if value=='AC':
number_entry.delete(0,'end')
print("AC pressed")
else: # 그외에 0부터 9까지 숫자일때
number_entry.insert("end",value)
print(value,"pressed")
# 사칙연산 처리
def math_button_pressed(value):
global operation #함수 바깥의 글로벌 변수사용
global temp_number
if not number_entry.get() == '': #기존에 입력한 숫자가 있을때만 연산버튼 인식
operation = value
temp_number = int(number_entry.get()) #입력된 숫자를 임시변수로 옮기고,
number_entry.delete(0,'end') #입력칸을 비우고, 다음숫자를 입력받을 준비.
print(temp_number,operation)
# 결과 버튼 처리
def equal_button_pressed():
global operation
global temp_number
#연산자나 숫자가 입력되지 않으면, 실행하지 않음.
if not (operation =='' and number_entry.get()==''):
number = int(number_entry.get())
if operation == '/':
solution = temp_number/number
elif operation == '*':
solution = temp_number*number
elif operation == '+':
solution = temp_number+number
else :
solution = temp_number-number
# 계산후, 숫자표시칸을 비우고, 계산결과를 표시.
number_entry.delete(0,'end')
number_entry.insert(0,solution)
print(temp_number,operation,number,"=",solution)
operation = ''
temp_number = 0
root = Tk()
root.title("Calculator")
root.geometry("300x200")
entry_value = StringVar(root, value='')
number_entry = ttk.Entry(root, textvariable = entry_value, width=20)
number_entry.grid(row=0, columnspan=3)
button7 = ttk.Button(root, text="7", command = lambda:button_pressed('7'))
button7.grid(row=1, column=0)
button8 = ttk.Button(root, text="8", command = lambda:button_pressed('8'))
button8.grid(row=1, column=1)
button9 = ttk.Button(root, text="9", command = lambda:button_pressed('9'))
button9.grid(row=1, column=2)
button_div = ttk.Button(root, text="/", command = lambda:math_button_pressed('/'))
button_div.grid(row=1, column=3)
button4 = ttk.Button(root, text="4", command = lambda:button_pressed('4'))
button4.grid(row=2, column=0)
button5 = ttk.Button(root, text="5", command = lambda:button_pressed('5'))
button5.grid(row=2, column=1)
button6 = ttk.Button(root, text="6", command = lambda:button_pressed('6'))
button6.grid(row=2, column=2)
button_mult = ttk.Button(root, text="*", command = lambda:math_button_pressed('*'))
button_mult.grid(row=2, column=3)
button1 = ttk.Button(root, text="1", command = lambda:button_pressed('1'))
button1.grid(row=3, column=0)
button2 = ttk.Button(root, text="2", command = lambda:button_pressed('2'))
button2.grid(row=3, column=1)
button3 = ttk.Button(root, text="3", command = lambda:button_pressed('3'))
button3.grid(row=3, column=2)
button_add = ttk.Button(root, text="+", command = lambda:math_button_pressed('+'))
button_add.grid(row=3, column=3)
button_ac = ttk.Button(root, text="AC", command = lambda:button_pressed('AC'))
button_ac.grid(row=4, column=0)
button0 = ttk.Button(root, text="0", command = lambda:button_pressed('0'))
button0.grid(row=4, column=1)
button_equal = ttk.Button(root, text="=", command = lambda:equal_button_pressed())
button_equal.grid(row=4, column=2)
button_sub = ttk.Button(root, text="-", command = lambda:math_button_pressed('-'))
button_sub.grid(row=4, column=3)
root.mainloop()

 

 

버그수정 #1 : 연속계산

한번 계산후에, 다른숫자를 입력하면, 기존결과를 지우고, 새로 계산하도록 하겠습니다.

이를 위해서, 결과출력 상태를 저장하는 answer_trigger 변수를 True/False 형태로 boolean 으로 사용하도록 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from tkinter import *
from tkinter import ttk
operation = ''
temp_number = 0
# 결과 출력 상태인지 상태저장.
answer_trigger = False
def button_pressed(value):
global temp_number
global answer_trigger
if value=='AC':
number_entry.delete(0,'end')
operation = ''
#AC버튼 누르면, trigger 변수도 초기화.
answer_trigger = False
print("AC pressed")
else:
#Trigger가 True이면, Entry 초기화후 새로입력.
if answer_trigger:
number_entry.delete(0,"end")
answer_trigger = False
number_entry.insert("end",value)
print(value,"pressed")
def math_button_pressed(value):
global operation
global temp_number
global answer_trigger
if not number_entry.get() == '':
operation = value
temp_number = int(number_entry.get())
number_entry.delete(0,'end')
print(temp_number,operation)
def equal_button_pressed():
global operation
global temp_number
global answer_trigger
if not (operation =='' and number_entry.get()==''):
number = int(number_entry.get())
if operation == '/':
solution = temp_number/number
elif operation == '*':
solution = temp_number*number
elif operation == '+':
solution = temp_number+number
else :
solution = temp_number-number
number_entry.delete(0,'end')
number_entry.insert(0,solution)
print(temp_number,operation,number,"=",solution)
operation = ''
temp_number = 0
# 계산 완료후, Trigger 변수 True로 변경.
answer_trigger = True
root = Tk()
root.title("Calculator")
root.geometry("300x200")
entry_value = StringVar(root, value='')
number_entry = ttk.Entry(root, textvariable = entry_value, width=20)
number_entry.grid(row=0, columnspan=3)
button7 = ttk.Button(root, text="7", command = lambda:button_pressed('7'))
button7.grid(row=1, column=0)
button8 = ttk.Button(root, text="8", command = lambda:button_pressed('8'))
button8.grid(row=1, column=1)
button9 = ttk.Button(root, text="9", command = lambda:button_pressed('9'))
button9.grid(row=1, column=2)
button_div = ttk.Button(root, text="/", command = lambda:math_button_pressed('/'))
button_div.grid(row=1, column=3)
button4 = ttk.Button(root, text="4", command = lambda:button_pressed('4'))
button4.grid(row=2, column=0)
button5 = ttk.Button(root, text="5", command = lambda:button_pressed('5'))
button5.grid(row=2, column=1)
button6 = ttk.Button(root, text="6", command = lambda:button_pressed('6'))
button6.grid(row=2, column=2)
button_mult = ttk.Button(root, text="*", command = lambda:math_button_pressed('*'))
button_mult.grid(row=2, column=3)
button1 = ttk.Button(root, text="1", command = lambda:button_pressed('1'))
button1.grid(row=3, column=0)
button2 = ttk.Button(root, text="2", command = lambda:button_pressed('2'))
button2.grid(row=3, column=1)
button3 = ttk.Button(root, text="3", command = lambda:button_pressed('3'))
button3.grid(row=3, column=2)
button_add = ttk.Button(root, text="+", command = lambda:math_button_pressed('+'))
button_add.grid(row=3, column=3)
button_ac = ttk.Button(root, text="AC", command = lambda:button_pressed('AC'))
button_ac.grid(row=4, column=0)
button0 = ttk.Button(root, text="0", command = lambda:button_pressed('0'))
button0.grid(row=4, column=1)
button_equal = ttk.Button(root, text="=", command = lambda:equal_button_pressed())
button_equal.grid(row=4, column=2)
button_sub = ttk.Button(root, text="-", command = lambda:math_button_pressed('-'))
button_sub.grid(row=4, column=3)
root.mainloop()

 

버그수정 #2 : 소수점형태의 문자열을 int형으로 변환시 오류. 조건부로 float형으로 변환

나눗셈에서 소수점이 생긴후, 이 숫자를 다시 계산하고자 연산자를 입력하면, 소수점형태의 문자열을 int형 숫자로 바꾸는 과정을 거치게 되는데, 이때 오류가 발생합니다. 이때는, 간단한 float_filter()라는 함수를 만들어서, float형으로 바꿔주도록 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
from tkinter import *
from tkinter import ttk
operation = ''
temp_number = 0
answer_trigger = False
def button_pressed(value):
global temp_number
global answer_trigger
if value=='AC':
number_entry.delete(0,'end')
operation = ''
answer_trigger = False
print("AC pressed")
else:
if answer_trigger:
number_entry.delete(0,"end")
answer_trigger = False
number_entry.insert("end",value)
print(value,"pressed")
# 소수점으로 int형 변환시 에러가 날경우, float형으로 반환.
def float_filter(value):
try:
int(value)
return int(value)
except ValueError:
return float(value)
def math_button_pressed(value):
global operation
global temp_number
global answer_trigger
if not number_entry.get() == '':
operation = value
#float_filter 함수 호출.
temp_number = float_filter(number_entry.get())
number_entry.delete(0,'end')
print(temp_number,operation)
def equal_button_pressed():
global operation
global temp_number
global answer_trigger
if not (operation =='' and number_entry.get()==''):
number = int(number_entry.get())
if operation == '/':
solution = temp_number/number
elif operation == '*':
solution = temp_number*number
elif operation == '+':
solution = temp_number+number
else :
solution = temp_number-number
number_entry.delete(0,'end')
number_entry.insert(0,solution)
print(temp_number,operation,number,"=",solution)
operation = ''
temp_number = 0
answer_trigger = True
root = Tk()
root.title("Calculator")
root.geometry("300x200")
entry_value = StringVar(root, value='')
number_entry = ttk.Entry(root, textvariable = entry_value, width=20)
number_entry.grid(row=0, columnspan=3)
button7 = ttk.Button(root, text="7", command = lambda:button_pressed('7'))
button7.grid(row=1, column=0)
button8 = ttk.Button(root, text="8", command = lambda:button_pressed('8'))
button8.grid(row=1, column=1)
button9 = ttk.Button(root, text="9", command = lambda:button_pressed('9'))
button9.grid(row=1, column=2)
button_div = ttk.Button(root, text="/", command = lambda:math_button_pressed('/'))
button_div.grid(row=1, column=3)
button4 = ttk.Button(root, text="4", command = lambda:button_pressed('4'))
button4.grid(row=2, column=0)
button5 = ttk.Button(root, text="5", command = lambda:button_pressed('5'))
button5.grid(row=2, column=1)
button6 = ttk.Button(root, text="6", command = lambda:button_pressed('6'))
button6.grid(row=2, column=2)
button_mult = ttk.Button(root, text="*", command = lambda:math_button_pressed('*'))
button_mult.grid(row=2, column=3)
button1 = ttk.Button(root, text="1", command = lambda:button_pressed('1'))
button1.grid(row=3, column=0)
button2 = ttk.Button(root, text="2", command = lambda:button_pressed('2'))
button2.grid(row=3, column=1)
button3 = ttk.Button(root, text="3", command = lambda:button_pressed('3'))
button3.grid(row=3, column=2)
button_add = ttk.Button(root, text="+", command = lambda:math_button_pressed('+'))
button_add.grid(row=3, column=3)
button_ac = ttk.Button(root, text="AC", command = lambda:button_pressed('AC'))
button_ac.grid(row=4, column=0)
button0 = ttk.Button(root, text="0", command = lambda:button_pressed('0'))
button0.grid(row=4, column=1)
button_equal = ttk.Button(root, text="=", command = lambda:equal_button_pressed())
button_equal.grid(row=4, column=2)
button_sub = ttk.Button(root, text="-", command = lambda:math_button_pressed('-'))
button_sub.grid(row=4, column=3)
root.mainloop()

 

버그수정 #3 : 결과값 정수형으로 처리.

한번 float형으로 계산이 되기 시작하면, 오류는 앞에서 잡더라도, 2.0 처럼, 정수형으로 표현될수 있는 숫자까지도 모두 flaot형으로 출력이 됩니다. 이때는, int(number)==float(number) 가 true이면, 정수라는 판단하에, 정수로 변경해주도록 하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
from tkinter import *
from tkinter import ttk
operation = ''
temp_number = 0
answer_trigger = False
def button_pressed(value):
global temp_number
global answer_trigger
if value=='AC':
number_entry.delete(0,'end')
operation = ''
answer_trigger = False
print("AC pressed")
else:
if answer_trigger:
number_entry.delete(0,"end")
answer_trigger = False
number_entry.insert("end",value)
print(value,"pressed")
def float_filter(value):
try:
int(value)
return int(value)
except ValueError:
return float(value)
# 두값이 같으면 정수로 표현가능.==> 정수값으로 반환.
def int_changer(value):
if int(value) == float(value):
return int(value)
else:
return float(value)
def math_button_pressed(value):
global operation
global temp_number
global answer_trigger
if not number_entry.get() == '':
operation = value
temp_number = float_filter(number_entry.get())
number_entry.delete(0,'end')
print(temp_number,operation)
def equal_button_pressed():
global operation
global temp_number
global answer_trigger
if not (operation =='' and number_entry.get()==''):
number = int(number_entry.get())
if operation == '/':
solution = temp_number/number
elif operation == '*':
solution = temp_number*number
elif operation == '+':
solution = temp_number+number
else :
solution = temp_number-number
#int_changer() 함수를 한번 거쳐서, 값저장.
solution = int_changer(solution)
number_entry.delete(0,'end')
number_entry.insert(0,solution)
print(temp_number,operation,number,"=",solution)
operation = ''
temp_number = 0
answer_trigger = True
root = Tk()
root.title("Calculator")
root.geometry("300x200")
entry_value = StringVar(root, value='')
number_entry = ttk.Entry(root, textvariable = entry_value, width=20)
number_entry.grid(row=0, columnspan=3)
button7 = ttk.Button(root, text="7", command = lambda:button_pressed('7'))
button7.grid(row=1, column=0)
button8 = ttk.Button(root, text="8", command = lambda:button_pressed('8'))
button8.grid(row=1, column=1)
button9 = ttk.Button(root, text="9", command = lambda:button_pressed('9'))
button9.grid(row=1, column=2)
button_div = ttk.Button(root, text="/", command = lambda:math_button_pressed('/'))
button_div.grid(row=1, column=3)
button4 = ttk.Button(root, text="4", command = lambda:button_pressed('4'))
button4.grid(row=2, column=0)
button5 = ttk.Button(root, text="5", command = lambda:button_pressed('5'))
button5.grid(row=2, column=1)
button6 = ttk.Button(root, text="6", command = lambda:button_pressed('6'))
button6.grid(row=2, column=2)
button_mult = ttk.Button(root, text="*", command = lambda:math_button_pressed('*'))
button_mult.grid(row=2, column=3)
button1 = ttk.Button(root, text="1", command = lambda:button_pressed('1'))
button1.grid(row=3, column=0)
button2 = ttk.Button(root, text="2", command = lambda:button_pressed('2'))
button2.grid(row=3, column=1)
button3 = ttk.Button(root, text="3", command = lambda:button_pressed('3'))
button3.grid(row=3, column=2)
button_add = ttk.Button(root, text="+", command = lambda:math_button_pressed('+'))
button_add.grid(row=3, column=3)
button_ac = ttk.Button(root, text="AC", command = lambda:button_pressed('AC'))
button_ac.grid(row=4, column=0)
button0 = ttk.Button(root, text="0", command = lambda:button_pressed('0'))
button0.grid(row=4, column=1)
button_equal = ttk.Button(root, text="=", command = lambda:equal_button_pressed())
button_equal.grid(row=4, column=2)
button_sub = ttk.Button(root, text="-", command = lambda:math_button_pressed('-'))
button_sub.grid(row=4, column=3)
root.mainloop()

 

여기까지 하면, 기본적인 계산은 문제없이 다 되는것 같습니다. 다음토픽에서는, 키보드로 숫자와 연산자를 입력받도록 코드를 좀 바꿔보도록 하겠습니다.

댓글

댓글 본문
  1. user
    다 잘되는데 '='버튼을 누르면 값이 안나옵니다.
  2. nomadlife
    네 제가 변수를 햇갈렸네요.10번째줄에 temp_number 대신 operation 변수로 바꿔주시면 됩니다. 다시 보니 숨어있는 버그들이 꽤 있는거같네요. 저도 공부도 되고 좋으니 혹시 또 잘못된거 있으면 알려주세요. 글 내용은 조만간 업데이트 해놓도록 하겠습니다.
    대화보기
    • 김진호
      버그 수정 #1 10번 라인에 global temp_number가 아니라 global operation이 들어가야 하는거 아닌가요...?
      아니라면 죄송합니다 제가 자 ㄹ몰라서,,, 다만 button_pressed(value) 함수에 temp_number는 사용되지 않고 오히려 operation의 초기화 코드가 포함된 상태인데 global operation이 없어도 되는건지 궁금합니다..!
      좋은 소스 감사합니다
    버전 관리
    nomadlife
    현재 버전
    선택 버전
    공동공부
    graphittie 자세히 보기