Python/Chapter13. 객체지향+, GUI 프로그래밍

lullaby ·2025년 10월 1일

Python

목록 보기
13/13
post-thumbnail

1. 객체지향 프로그래밍 핵심 개념

1.1 클래스(Class)와 객체(Object)

  • 클래스: 객체를 만들기 위한 템플릿/설계도
  • 객체: 클래스의 인스턴스, 실제로 메모리에 할당된 실체
# 기본 클래스 정의 예시
class Rectangle:
    def __init__(self, side=0):  # 생성자 메서드
        self.side = side  # 인스턴스 변수

    def getArea(self):  # 인스턴스 메서드
        return self.side * self.side

# 객체 생성
myRect = Rectangle(5)
print(myRect.getArea())  # 25

1.2 클래스 변수와 인스턴스 변수

  • 클래스 변수: 클래스 내부에서 선언되며 모든 객체가 공유하는 변수
  • 인스턴스 변수: self.변수명으로 선언되며 각 객체마다 별도로 생성되는 변수
class Television:
    serialNumber = 0  # 클래스 변수

    def __init__(self):
        Television.serialNumber += 1  # 클래스 변수 접근
        self.number = Television.serialNumber  # 인스턴스 변수

a = Television()
b = Television()
c = Television()

print(a.serialNumber)  # 3 (모든 객체가 공유)
print(a.number)  # 1 (객체별 고유값)
print(b.number)  # 2
print(c.number)  # 3

1.3 특수 메서드(Special Methods)

image.png

  • __init__: 생성자 메서드
  • __eq__: 두 객체의 동등성 비교 (== 연산자)
  • __lt__: 크기 비교 (< 연산자)
  • __add__, __sub__ 등: 산술 연산자 오버로딩
class Circle:
    def __init__(self, radius):
        self.radius = radius

    def __eq__(self, other):
        return self.radius == other.radius

    def __lt__(self, other):
        return self.radius < other.radius

c1 = Circle(10)
c2 = Circle(100)

print(c1 == c2)  # False
print(c1 < c2)   # True

1.4 벡터 연산 예제

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector2D(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        return Vector2D(self.x - other.x, self.y - other.y)

    def __str__(self):
        return '(%d, %d)' % (self.x, self.y)

u = Vector2D(0, 1)
v = Vector2D(1, 1)
result = u + v
print(result)  # (1, 2)

2. GUI 프로그래밍 핵심 개념

2.1 tkinter 기본 구조

from tkinter import *

window = Tk()  # 윈도우 생성
# 위젯 배치
window.mainloop()  # 이벤트 루프 시작

2.2 주요 위젯

image.png

위젯설명
Label텍스트나 이미지 표시
Button클릭 가능한 버튼
Entry한 줄 텍스트 입력 필드
Text여러 줄 텍스트 표시/편집
Frame다른 위젯을 그룹화하는 컨테이너
Canvas그래픽 그리기 위한 영역

2.3 위젯 배치 관리자

  • pack(): 상대적 위치로 배치 (TOP, BOTTOM, LEFT, RIGHT)
  • grid(): 격자 형태로 배치 (row, column)
  • place(): 절대 위치로 배치 (x, y)
# pack() 예시
label = Label(window, text="Hello")
label.pack(side=LEFT)

# grid() 예시
label1 = Label(window, text="이름")
label1.grid(row=0, column=0)
entry1 = Entry(window)
entry1.grid(row=0, column=1)

2.4 이벤트 처리

def callback():
    button["text"] = "버튼이 클릭되었음!"

button = Button(window, text="클릭", command=callback)

2.5 계산기 예제 (코어 로직)

from tkinter import *

def click(key):
    if key == '=':  # '=' 버튼이면 수식을 계산하여 결과를 표시
        try:
            result = eval(entry.get())
            entry.delete(0, END)  # 0번째 위치부터 끝까지 삭제
            entry.insert(END, str(result))
        except:
            entry.insert(END, "오류!")
    elif key == 'C':
        entry.delete(0, END)
    else:
        entry.insert(END, key)

window = Tk()
window.title("계산기")

buttons = ['7', '8', '9', '+', 'C',
           '4', '5', '6', '-', ' ',
           '1', '2', '3', '*', ' ',
           '0', '.', '=', '/', ' ']
           
# 반복문으로 버튼을 생성한다.
i = 0
for b in buttons:
    b = Button(window, text=b, width=5, relief='ridge', command=lambda x=b: click(x))
    b.grid(row=i//5+1, column=i%5)
    i += 1

# 엔트리 위젯은 5개의 셀을 병합한 너비로 맨 위에 배치된다.
entry = Entry(window, width=33, bg="yellow")
entry.grid(row=0, column=0, columnspan=5)

window.mainloop()

3. 예상 문제 및 풀이

파이썬 기말고사 대비 예상 문제 및 풀이

객체지향 프로그래밍

문제 1: 클래스와 객체 기초

다음 코드의 실행 결과는 무엇인가?

class Counter:
    count = 0

    def __init__(self):
        Counter.count += 1
        self.id = Counter.count

    def get_id(self):
        return self.id

a = Counter()
b = Counter()
print(a.count, b.count)
print(a.id, b.id)

풀이:

2 2
1 2

클래스 변수 count는 모든 객체가 공유하므로 두 객체 모두 2가 출력됩니다.
인스턴스 변수 id는 각 객체마다 다른 값을 가지므로 a는 1, b는 2가 출력됩니다.

문제 2: 특수 메서드

다음 코드를 실행했을 때 에러가 발생하지 않도록 __lt__ 메서드를 구현하시오.

class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    # 여기에 __lt__ 메서드를 구현하세요

students = [Student("Kim", 85), Student("Lee", 92), Student("Park", 78)]
sorted_students = sorted(students)
for student in sorted_students:
    print(f"{student.name}: {student.score}")

풀이:

def __lt__(self, other):
    return self.score < other.score

문제 3: 벡터 연산

2차원 벡터를 나타내는 Vector2D 클래스에 곱셈 연산(*)을 지원하도록 __mul__ 메서드를 구현하시오. 벡터와 스칼라 값의 곱셈을 지원해야 합니다.

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"({self.x}, {self.y})"

    # 여기에 __mul__ 메서드를 구현하세요

v = Vector2D(3, 4)
result = v * 2
print(result)  # 출력: (6, 8)

풀이:

def __mul__(self, scalar):
    return Vector2D(self.x * scalar, self.y * scalar)

GUI 프로그래밍

문제 4: 버튼 이벤트 처리

다음 코드에서 버튼을 클릭할 때마다 카운터가 증가하도록 increase_counter 함수를 구현하시오.

from tkinter import *

def increase_counter():
    # 여기에 코드를 구현하세요

window = Tk()
counter = 0
label = Label(window, text="카운터: 0")
label.pack()

button = Button(window, text="증가", command=increase_counter)
button.pack()

window.mainloop()

풀이:

def increase_counter():
    global counter
    counter += 1
    label.config(text=f"카운터: {counter}")

문제 5: Entry 위젯 활용

다음 조건을 만족하는 간단한 온도 변환기(섭씨→화씨) GUI 프로그램의 convert 함수를 완성하시오.

from tkinter import *

def convert():
    # 여기에 코드를 구현하세요

window = Tk()
window.title("온도 변환기")

Label(window, text="섭씨(°C):").grid(row=0, column=0)
celsius_entry = Entry(window)
celsius_entry.grid(row=0, column=1)

Label(window, text="화씨(°F):").grid(row=1, column=0)
fahrenheit_label = Label(window, text="")
fahrenheit_label.grid(row=1, column=1)

Button(window, text="변환", command=convert).grid(row=2, column=1)

window.mainloop()

풀이:

def convert():
    try:
        celsius = float(celsius_entry.get())
        fahrenheit = (celsius * 9/5) + 32
        fahrenheit_label.config(text=f"{fahrenheit:.2f}")
    except ValueError:
        fahrenheit_label.config(text="오류: 숫자를 입력하세요")

문제 6: 산수 퀴즈 프로그램

다음 산수 퀴즈 프로그램에서 check_answer 함수를 완성하여, 사용자의 답을 확인하고 결과를 표시하시오.

from tkinter import *
import random

def generate_question():
    global a, b, operation
    a = random.randint(1, 10)
    b = random.randint(1, 10)
    operation = random.choice(['+', '-', '*'])
    question_label.config(text=f"{a} {operation} {b} = ?")
    answer_entry.delete(0, END)
    result_label.config(text="")

def check_answer():
    # 여기에 코드를 구현하세요

window = Tk()
window.title("산수 퀴즈")

a, b, operation = 0, 0, '+'

question_label = Label(window, font=('Arial', 14))
question_label.pack(pady=10)

answer_entry = Entry(window)
answer_entry.pack(pady=5)

Button(window, text="확인", command=check_answer).pack(pady=5)
Button(window, text="새 문제", command=generate_question).pack(pady=5)

result_label = Label(window, font=('Arial', 12))
result_label.pack(pady=10)

generate_question()
window.mainloop()

풀이:

def check_answer():
    try:
        user_answer = int(answer_entry.get())
        if operation == '+':
            correct_answer = a + b
        elif operation == '-':
            correct_answer = a - b
        else:  # '*'
            correct_answer = a * b

        if user_answer == correct_answer:
            result_label.config(text="정답입니다!", fg="green")
        else:
            result_label.config(text=f"오답입니다. 정답은 {correct_answer}입니다.", fg="red")
    except ValueError:
        result_label.config(text="숫자를 입력하세요", fg="red")

파이썬 객체지향 프로그래밍 & GUI 기말고사 대비 요약 정리

객체지향 프로그래밍

1. 객체와 클래스의 기본 개념

  • 클래스(Class): 객체를 생성하기 위한 템플릿/설계도
  • 객체(Object): 클래스의 인스턴스(실체)
  • 속성(Attribute): 객체의 특성을 나타내는 변수
  • 메서드(Method): 객체가 수행할 수 있는 동작/함수
# 기본 클래스 구조
class ClassName:
    # 생성자 메서드
    def __init__(self, parameter1, parameter2):
        self.attribute1 = parameter1  # 인스턴스 변수
        self.attribute2 = parameter2

    # 일반 메서드
    def method1(self):
        # 메서드 내용
        pass

2. 변수 유형

변수 유형설명예제
클래스 변수모든 객체가 공유하는 변수ClassName.variable
인스턴스 변수각 객체마다 독립적인 변수self.variable
지역 변수메서드 내에서만 사용 가능한 변수variable
class Television:
    serialNumber = 0  # 클래스 변수

    def __init__(self):
        Television.serialNumber += 1
        self.number = Television.serialNumber  # 인스턴스 변수

    def display(self):
        count = 1  # 지역 변수
        print(f"TV #{self.number}, 총 TV 개수: {Television.serialNumber}")

3. 특수 메서드(Magic Methods)

메서드연산자설명
__init__(self, ...)-객체 초기화(생성자)
__str__(self)str()문자열 표현 반환
__eq__(self, other)==동등성 비교
__lt__(self, other)<작음 비교
__add__(self, other)+덧셈
__sub__(self, other)-뺄셈
__mul__(self, other)*곱셈
__truediv__(self, other)/나눗셈
__floordiv__(self, other)//정수 나눗셈
__mod__(self, other)%나머지
class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"({self.x}, {self.y})"

    def __add__(self, other):
        return Vector2D(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        return Vector2D(self.x - other.x, self.y - other.y)

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

4. 객체와 함수의 관계

class Rectangle:
    def __init__(self, side=0):
        self.side = side

    def getArea(self):
        return self.side * self.side

# 객체를 함수에 전달
def printAreas(r, n):
    while n >= 1:
        print(f"n = {n}, r.side = {r.side}, r.getArea() = {r.getArea()}")
        r.side = r.side + 1
        n = n - 1

# 함수 호출
myRect = Rectangle()
count = 5
printAreas(myRect, count)
print(f"함수 탈출 후 myRect.side = {myRect.side}")  # 5

GUI 프로그래밍 (tkinter)

1. tkinter 기본 구조

from tkinter import *

window = Tk()  # 윈도우 생성
window.title("제목")  # 윈도우 제목 설정

# 위젯 배치 코드

window.mainloop()  # 이벤트 루프 시작

2. 주요 위젯

위젯설명생성 예시
Label텍스트/이미지 표시Label(window, text="텍스트")
Button클릭 가능한 버튼Button(window, text="버튼", command=함수명)
Entry한 줄 텍스트 입력Entry(window)
Text여러 줄 텍스트 입력/표시Text(window, height=5, width=30)
Frame다른 위젯 그룹화Frame(window)
Canvas그래픽 그리기Canvas(window, width=300, height=200)
Checkbutton체크박스Checkbutton(window, text="체크")
Radiobutton라디오 버튼Radiobutton(window, text="옵션")
Listbox선택 목록Listbox(window)
Scrollbar스크롤바Scrollbar(window)
Menu메뉴Menu(window)
PhotoImage이미지 표시용PhotoImage(file="이미지.gif")

3. 배치 관리자

배치 관리자설명예시
pack()상대적 위치로 배치widget.pack(side=LEFT, padx=10, pady=5)
grid()행과 열 기반 배치widget.grid(row=0, column=1)
place()절대 위치로 배치widget.place(x=100, y=200)

pack() 옵션

  • side: TOP(기본값), BOTTOM, LEFT, RIGHT
  • fill: X, Y, BOTH, NONE
  • expand: 0(기본값) 또는 1
  • padx, pady: 여백

grid() 옵션

  • row, column: 배치할 행과 열 (0부터 시작)
  • rowspan, columnspan: 병합할 행/열 수
  • padx, pady: 여백

4. 이벤트 처리

# 방법 1: command 옵션 사용
def button_clicked():
    label.config(text="버튼이 클릭되었습니다!")

button = Button(window, text="클릭", command=button_clicked)

# 방법 2: bind() 메서드 사용
def key_pressed(event):
    print(f"키가 눌렸습니다: {event.char}")

entry.bind("<Key>", key_pressed)

5. 위젯 속성 변경

# 생성 시 설정
label = Label(window, text="원래 텍스트", fg="blue", bg="yellow")

# 나중에 변경
label["text"] = "변경된 텍스트"  # 딕셔너리 형태로 접근
label.config(text="새로운 텍스트", fg="red")  # config() 메서드 사용

6. 계산기 응용 프로그램

from tkinter import *

def click(key):
    if key == '=':  # 계산 실행
        try:
            result = eval(entry.get())
            entry.delete(0, END)
            entry.insert(END, str(result))
        except:
            entry.insert(END, "오류!")
    elif key == 'C':  # 입력 내용 지우기
        entry.delete(0, END)
    else:  # 다른 키는 화면에 추가
        entry.insert(END, key)

window = Tk()
window.title("계산기")

# 계산 결과 표시창
entry = Entry(window, width=33, bg="yellow")
entry.grid(row=0, column=0, columnspan=5)

# 버튼 배열 정의
buttons = ['7', '8', '9', '+', 'C',
           '4', '5', '6', '-', ' ',
           '1', '2', '3', '*', ' ',
           '0', '.', '=', '/', ' ']

# 버튼 생성 및 배치
i = 0
for b in buttons:
    button = Button(window, text=b, width=5, relief='ridge',
                   command=lambda x=b: click(x))
    button.grid(row=i//5+1, column=i%5)
    i += 1

자주 실수하는 부분과 주요 포인트

객체지향 프로그래밍

  1. self 매개변수 누락: 모든 인스턴스 메서드의 첫 매개변수는 반드시 self
  2. 클래스 변수와 인스턴스 변수 혼동: 용도에 맞게 사용
  3. 특수 메서드 구현 시 매개변수 개수/이름 확인: __add__(self, other)

GUI 프로그래밍

  1. mainloop() 호출 누락: 이벤트 루프 시작을 위해 필수
  2. 위젯 생성과 배치 분리: button = Button(...); button.pack() 또는 Button(...).pack()
  3. 전역 변수 사용 시 global 키워드 필요: 함수 내에서 전역 변수 변경 시
  4. 람다 함수 사용 시 매개변수 전달 주의: command=lambda x=value: function(x)
  5. 이벤트 처리 함수에서 이벤트 객체(event) 처리: bind 사용 시 필요

예상 문제 및 풀이

파이썬 기말고사 대비 예상 문제 및 풀이

객체지향 프로그래밍

문제 1: 클래스와 객체 기초

다음 코드의 실행 결과는 무엇인가?

class Counter:
    count = 0

    def __init__(self):
        Counter.count += 1
        self.id = Counter.count

    def get_id(self):
        return self.id

a = Counter()
b = Counter()
print(a.count, b.count)
print(a.id, b.id)

풀이:

2 2
1 2

클래스 변수 count는 모든 객체가 공유하므로 두 객체 모두 2가 출력됩니다.
인스턴스 변수 id는 각 객체마다 다른 값을 가지므로 a는 1, b는 2가 출력됩니다.

문제 2: 특수 메서드

다음 코드를 실행했을 때 에러가 발생하지 않도록 __lt__ 메서드를 구현하시오.

class Student:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    # 여기에 __lt__ 메서드를 구현하세요

students = [Student("Kim", 85), Student("Lee", 92), Student("Park", 78)]
sorted_students = sorted(students)
for student in sorted_students:
    print(f"{student.name}: {student.score}")

풀이:

def __lt__(self, other):
    return self.score < other.score

문제 3: 벡터 연산

2차원 벡터를 나타내는 Vector2D 클래스에 곱셈 연산(*)을 지원하도록 __mul__ 메서드를 구현하시오. 벡터와 스칼라 값의 곱셈을 지원해야 합니다.

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"({self.x}, {self.y})"

    # 여기에 __mul__ 메서드를 구현하세요

v = Vector2D(3, 4)
result = v * 2
print(result)  # 출력: (6, 8)

풀이:

def __mul__(self, scalar):
    return Vector2D(self.x * scalar, self.y * scalar)

GUI 프로그래밍

문제 4: 버튼 이벤트 처리

다음 코드에서 버튼을 클릭할 때마다 카운터가 증가하도록 increase_counter 함수를 구현하시오.

from tkinter import *

def increase_counter():
    # 여기에 코드를 구현하세요

window = Tk()
counter = 0
label = Label(window, text="카운터: 0")
label.pack()

button = Button(window, text="증가", command=increase_counter)
button.pack()

window.mainloop()

풀이:

def increase_counter():
    global counter
    counter += 1
    label.config(text=f"카운터: {counter}")

문제 5: Entry 위젯 활용

다음 조건을 만족하는 간단한 온도 변환기(섭씨→화씨) GUI 프로그램의 convert 함수를 완성하시오.

from tkinter import *

def convert():
    # 여기에 코드를 구현하세요

window = Tk()
window.title("온도 변환기")

Label(window, text="섭씨(°C):").grid(row=0, column=0)
celsius_entry = Entry(window)
celsius_entry.grid(row=0, column=1)

Label(window, text="화씨(°F):").grid(row=1, column=0)
fahrenheit_label = Label(window, text="")
fahrenheit_label.grid(row=1, column=1)

Button(window, text="변환", command=convert).grid(row=2, column=1)

window.mainloop()

풀이:

def convert():
    try:
        celsius = float(celsius_entry.get())
        fahrenheit = (celsius * 9/5) + 32
        fahrenheit_label.config(text=f"{fahrenheit:.2f}")
    except ValueError:
        fahrenheit_label.config(text="오류: 숫자를 입력하세요")

문제 6: 산수 퀴즈 프로그램

다음 산수 퀴즈 프로그램에서 check_answer 함수를 완성하여, 사용자의 답을 확인하고 결과를 표시하시오.

from tkinter import *
import random

def generate_question():
    global a, b, operation
    a = random.randint(1, 10)
    b = random.randint(1, 10)
    operation = random.choice(['+', '-', '*'])
    question_label.config(text=f"{a} {operation} {b} = ?")
    answer_entry.delete(0, END)
    result_label.config(text="")

def check_answer():
    # 여기에 코드를 구현하세요

window = Tk()
window.title("산수 퀴즈")

a, b, operation = 0, 0, '+'

question_label = Label(window, font=('Arial', 14))
question_label.pack(pady=10)

answer_entry = Entry(window)
answer_entry.pack(pady=5)

Button(window, text="확인", command=check_answer).pack(pady=5)
Button(window, text="새 문제", command=generate_question).pack(pady=5)

result_label = Label(window, font=('Arial', 12))
result_label.pack(pady=10)

generate_question()
window.mainloop()

풀이:

def check_answer():
    try:
        user_answer = int(answer_entry.get())
        if operation == '+':
            correct_answer = a + b
        elif operation == '-':
            correct_answer = a - b
        else:  # '*'
            correct_answer = a * b

        if user_answer == correct_answer:
            result_label.config(text="정답입니다!", fg="green")
        else:
            result_label.config(text=f"오답입니다. 정답은 {correct_answer}입니다.", fg="red")
    except ValueError:
        result_label.config(text="숫자를 입력하세요", fg="red")

0개의 댓글