안내: Think Python 4장과 How to Think Like a Computer Scientist: Learning with Python 3 내용의 일부를 번역 및 수정하여 활용한 내용입니다.
객체 지향 프로그래밍(Object-Oriented Programming)을 줄여서 보통 OOP라고 부른다.
OOP는 프로그래밍 기법 중의 하나이며 OOP를 지원하는 언어를 객체 지향 언어라고 부른다. 파이썬을 포함하여 자바, C++, C#, 루비, 자바스크립트 등 많은 컴퓨터 프로그래밍 언어가 객체 지향을 지원한다.
OOP와 대비되는 개념으로 절차 지향 프로그래밍이 주로 언급된다. 절차 지향 프로그래밍은 수행해야 할 일을 순차적으로 처리하는 과정을 묘사하는 것을 가장 중요하게 여기며 프로그램 전체가 유기적으로 연결되도록 만드는 프로그래밍 기법이다. C, HTML 등이 대표적인 절차 지향 프로그래밍언어이다.
"해야 할 일을 순차적으로 처리한다"는 표현은 가장 기본적인 프로그래밍 기법이며, 모든 프로그램은 원하는 결과를 얻기 위한 과정을 논리적이며 순차적으로 처리하도록 구현되어야 한다.
OOP 역시 예외가 아니다. 하지만 OOP는 구현해야 할 객체들을 선택하고 객체들 사이의 유기적인 관계를 논리적으로 묘사하는 데에 보다 많은 방점을 둔다. 즉, 프로그램 전체를 하나로 묶어서 구현하는 방식이 아니라 프로그램을 구성하는 객체들을 중심으로 해서 구현해야 할 프로그램을 완성시키는 방식으로 프로그래밍을 진행한다.
OOP에 대한 이해는 아래 두 가지 질문과 관련되어 있다.
위 질문들에 대한 직접적인 설명 대신에 객체가 어떻게 활용되는가를 실전 예제를 통해 소개한다.
그림그리기와 관련된 도구를 담고 있는 turtle
모듈을 소개한다.
turtle
모듈은 파이썬에 기본적으로 포함되어 있다.
turtle
모듈에 대한 상세한 설명은
이곳 참조할 것을 추천한다.
여기서는 간단한 예제를 통해 객체(인스턴스)를 클래스의 인스턴스로
구하는 과정을 보여주고자 한다.
먼저 아래 코드를 mypolygon1.py
파일에 저장하고 실행해 보자.
import turtle
wn = turtle.Screen()
bob = turtle.Turtle()
bob.forward(100)
bob.left(90)
bob.forward(100)
bob.left(90)
bob.forward(100)
bob.left(90)
bob.forward(100)
bob.left(90)
wn.mainloop()
그러면 아래 이미지처럼 한 변의 길이가 100인 정사각형을 그리는 화살촉의 움직임을 볼 수 있을 것이다.
주의: 픽셀(pixel, 화소)은 컴퓨터 모니터 등과 같은 디지털 화면를 구성하는 기본 단위이다. 소위 해상도란 바로 픽셀의 개수를 일컫는다. 예를 들어, Full HD(FHD)의 해상도는 1920×1080으로 표시되는데 이는 화면을 가로 1920칸, 세로 1080칸의 격자무늬로 쪼갠 후에 각각의 격자에 하나의 색 정보가 입력되었을 의미한다. 이런 격자 하나하나를 픽셀이라 부른다. 해상도가 높아질 수록 픽셀 수가 많아지며 따라서 보다 선명한 색채구현히 가능해진다.
이제 위 코드를 한 줄씩 살펴보자.
turtle
모듈을 불러온다.import turtle
turtle
모듈에 포함된 Screen
함수는 같은 모듈에 선언되어 있는
TurtleScreen
클래스의 인스턴스(객체)를 하나 생성해서 리턴값으로 내준다.wn = turtle.Screen()
TurtleScreen
클래스의 인스턴스를 하나 생성한다는 것은
그림을 그릴 도화지(캔버스)를 한 장 준비한다는 의미이다.
즉, 위 그림에서처럼 정사각형를 그릴 도화지 역할을 수행하는 창을 하나 생성한다.도화지 속성 변경: 도화지 창에 이름을 지정할 수 있다.
기본값은 Python Turtle Graphics이며 _title
라는 (숨은)
속성에 저장되어 있다.
주의: 밑줄(언더스코어, underscore)로 시작하는 변수는 숨겨진 변수를 가리킨다. 즉, 사용자가 일부러 선택하여 값을 지정하기 보다는 다른 도구를 활용하라는 의미이다.
도화지의 이름을 지정하려면 title
이라는 함수를 아래와 같이 활용하면 된다.
예를 들어, 도화지의 이름을 'Hello, Bob and Alice!'로 지정하려면 아래와 같이 실행한다.
wn.title("Hello, Bob and Alice!")
turtle
모듈에서 정의되어 있는 Turtle
클래스의 인스턴스(객체)를 하나 생성해서 bob
변수에 할당한다.bob = turtle.Turtle()
Turtle
클래스의 인스턴스를 하나 생성한다는 것은 그림을 그리는 도구인 펜을 하나 준비한다는 의미이다.
즉, 아래 그림의 화살촉 모양처럼 선을 그리는 펜 역할을 수행하는 도구를 하나 생성한다.bob.forward(100)
bob.left(90)
bob.forward(100)
bob.left(90)
bob.forward(100)
bob.left(90)
bob.forward(100)
bob.left(90)
X
버튼이 눌릴 때까지 유지시킨다. wn.mainloop()
거북이 속성 변경:
그림 그릴 때 사용되는 펜의 색깔인 검은색은 _pencolor
라는 (숨은) 속성에 저장되어 있다.
아래와 같이 확인할 수 있다.
print(bob._pencolor)
주의: _pencolor
또한 숨겨진 변수이다.
펜의 색깔을 지정하려면 pencolor
라는 메서드를 아래와 같이 활용하면 된다.
예를 들어, 펜의 색깔을 옅노랑(light yellow)로 지정하려면 아래와 같이 실행한다.
print(bob.pencolor("lightyellow"))
아래 내용을 기억하고 있어야 한다.
클래스에서 선언된 변수와 함수들은 해당 클래스를 통하여 또는 해당 클래스의 인스턴스를 통하여 호출될 수 있다.
특정 클래스의 인스턴스(instance)는 해당 클래스에서 선언된 속성과 기능을 모두 물려받는 대상을 의미한다. 객체(object)는 특정 클래스의 인스턴스를 부르는 보다 일반적인 표현이다.
참고: 파이썬에서 사용되는 모든 값은 특정 클래스의 인스턴스, 즉 객체로 선언된다.
지금까지 사용해왔던 모든 자료형들도 모두 클래스로 정의되어 있다.
심지어는 클래스 조차도 type
이라는 클래스의 객체이다.
앞서 소개한 거북이 그래픽 예제에서 사용된 turtle
모듈과 관련된 프로그래밍 기본요소는 다음과 같다.
turtle
Screen
(대문자로 시작하는 이름에 주의)TurtleScreen
, Turtle
TurtleScreen
클래스
wn
_title
title
, mainloop
Turtle
클래스
bob
_pencolor
pencolor
, left
, forward
Screen
함수의 리턴값¶엄밀히 말하면 Screen
함수의 리턴값은 TurtleScreen
의
자식 클래스인 _Screen
클래스의 인스턴스이다.
하지만 사용된 밑줄에서 알 수 있듯이 숨겨진 클래스이기 때문에 부모 클래스인 TurtleScreen
을
기본적으로 언급한다.
또한 Screen
함수의 리턴값은 _Screen
클래스의 싱글턴 객체(singleton object)이다.
싱글톤 객체라 함은 해당 클래스의 인스턴스가 하나 뿐이라는 말이다.
따라서 Screen
함수를 이용하여 생성할 수 있는 도화지는 단 하나뿐이다.
클래스에서 선언된 메서드와 변수를 사용법에 따라 여러 종류로 분류할 수 있다.
변수와 메서드의 종류에 대한 보다 상세한 설명은 코드 추상화: 클래스와 객체 1부와 2부에서 다룬다.
클래스를 이용하여 생성한 객체들은 기본적으로 상호 독립적으로 활용된다. 하지만 객체들 사이의 상호 교감도 가능하다. 따라서 각각의 객체가 수행하는 기능과 객체들 사이의 교감을 중심으로 해서 프로그램을 작성하는 것이 객체를 중심으로 프로그래밍한다의 기본 의미이다.
여기서는 Turtle
클래스의 인스턴스를 두 개 생성하여,
생성된 두 객체를 상호 독립적으로 활용하는 방법을 설명한다.
객체들 사이의 교감을 구현하는 방식은 나중에 다룰 것이다.
아래 코드를 mypolygon2.py
파일에 저장하고 실행하면 두 개의 펜을 이용하여 사각형과 삼각형을 그린 결과를 얻을 것이다.
mypolygon.py
와는 달리 반복되는 코드를 for
반복문으로 묶었다.
아래 코드에서 Turtle
클래스의 인스턴스가 두 번 생성되었다.
또한 alice
객체에 대해세만 아래 인스턴스 메서드가 추가로 사용되었다.
shape
: 해당 인스턴스의 펜 모양을 지정된 모양으로 변경시킴color
: 해당 인스턴스의 선 색깔을 지정된 색깔로 변경시킴주의: alice
의 속성을 변경한다 하더라도 bob
의 속성은 전혀 변하지 않는다.
자세한 설명은
코드 추상화: 클래스와 객체 1부를
참조한다.
import turtle
wn = turtle.Screen()
# bob 생성
bob = turtle.Turtle()
# alice 생성
alice = turtle.Turtle()
alice.shape("turtle") # 펜 모양을 거북이로 변경
alice.color("red") # 선 색깔을 빨강으로 변경
alice.penup() # 펜 들기: 선 그리지 않음
alice.backward(100) # 뒤로 100픽셀 이동
alice.pendown() # 펜 내리기: 선 그리기 시작함
# bob 으로 사각형 그리기
for i in range(4):
bob.forward(100)
bob.left(90)
# alice로 삼각형 그리기
for i in range(3):
alice.forward(100)
alice.right(120) # 시계방향으로 회전
wn.mainloop()
아래 코드를 mypolygon3.py
파일에 저장하고 실행하면
이전 코드와는 달리 배경화면의 색깔과 그림 제목을 다르게 지정한 것을 확인 할 수 있다.
bgcolor
: Screen
클래스의 인스턴스 메서드. 그림의 배경화면 색 지정title
: Screen
클래스의 인스턴스 메서드. 그림의 제목 지정import turtle
wn = turtle.Screen()
wn.bgcolor("lightyellow") # 배경화면 색깔 정하기
wn.title("Hello, Bob and Alice!") # 그래픽 제목 정하기
# bob 생성
bob = turtle.Turtle()
# alice 생성
alice = turtle.Turtle()
alice.shape("turtle")
alice.color("red")
alice.penup()
alice.backward(100)
alice.pendown()
# bob 으로 사각형 그리기
for i in range(4):
bob.forward(100)
bob.left(90)
# alice로 삼각형 그리기
for i in range(3):
alice.forward(100)
alice.right(120)
wn.mainloop()
turtle
모듈 정보¶turtle
모듈에 포함된 클래스와 클래스 메서드와 속성의 활용법은
docs.python.org를
참조한다.
또한 turtle
모듈의 소스코드는
cpython의 turtle.py에서
확인할 수 있다.
Turtle
클래스의 메서드 소개¶Turtle
클래스의 메서드 일부를 소개한다.
아래에 언급된 메서드의 기능은
realpython.com에서
확인할 수 있다.
goto
: 도화지의 중심을 원점으로 하며 2차원 상의 좌표를 지정하여 거북이를 이동시킨다. bob.goto(100)
home
: 원점, 즉, 도화지의 중심으로 거북이를 돌려 보낸 후, 오른쪽을 바라보도록 한다.bob.home()
fd
, forward
: 현재 바라보는 방향으로 전진bd
, backward
: 현재 바라보는 방향 반대편으로 후진. 바라보는 방향 유지.rt
, right
: 시계방향으로 90도 회전lt
, left
: 시계반대방향으로 90도 회전circle
: 원 그리기. 인자는 반지름.bob.circle(100)
dot
: 원반 그리기. 원 내부는 색으로 채워짐. 원의 지름과 색깔 지정 가능.bob.circle(20)
bob.circle(20,
red)
shape
: 거북이 모양 설정. 기본은 화살촉 모양.bob.shape('turtle')
wn.getshapes()
['arrow', 'square', 'triangle', 'classic', 'turtle', 'circle']
shapesize
: 거북이 크기 설정pensize
: 선 두께 지정bob.pensize(5)
fillcolor
: 거북이 내부 색상 지정bob.fillcolor('red')
color
: 선 및 내부 색상 지정bob.color('blue', 'red')
begin_fill
과 end_fill
: 두 메서드로 감싸인 코드에서 그린 도형 내부를 거북이 색으로 채우기bob.begin_fill()
bob.fd(100)
bob.lt(120)
bob.fd(100)
bob.lt(120)
bob.fd(100)
bob.end_fill()
speed
: 펜 속도 조절하기bob.speed(1)
가장 빠름 : 0
빠름 : 10
보통 : 6
느림 : 3
가장 느림 : 1
pen
: pencolor
, fillcolor
, pensize
, speed
등 펜과 관련된 여러 성질을 동시에 설정 가능.bob.pen(pencolor="purple", fillcolor="red", pensize="5", speed="8")
pd
, pendown
: 선 그리는 상태로 전환pu
, penup
: 선 그리지 않는 상태로 전환stamp
: 도장 찍기 down
: 거북이가 마지막으로 실행한 명령 취소clear
: 거북이가 그린 모든 도형 삭제. 거북이는 마직막 위치에 머무름.reset
: 거북이가 그린 모든 도형 삭제 및 거북이 초기화.clone
: 거북이 복제. 모든 상태 그대로 복제.
bobi = bob.clone()
bob.color("orange")
bobi.color("magenta")
bob.circle(100)
bobi.circle(60)
아래 코드를 mypolygon4.py
파일에 저장하고 실행하면
회오리 모양으로 움직이면서 점차 가속도가 붙는 거북이를 확인할 수 있다.
penup
: Turtle
클래스의 인스턴스 메서드. 그림 그리지 않는 상태로 전환.stamp
: Turtle
클래스의 인스턴스 메서드. 도장 찍기.import turtle
wn = turtle.Screen()
wn.bgcolor("lightyellow")
bob = turtle.Turtle()
bob.shape("turtle") # 화살촉 대신 거북이 모양 선택
bob.color("blue")
bob.penup() # 펜 들기 (이동할 때 선을 그리지 않게 됨)
size = 20
for i in range(30):
bob.stamp() # 거북이 모양 도장 찍기
size = size + 3 # 회전을 점차 크게 돌도록 만들기
bob.forward(size) # size 크기만큼 전진하기
bob.right(24) # 24도 우회전하기
wn.mainloop()
realpython.com에서 소개한 프로젝트이다.
작동 방식은 realpython.com: 거북이 경주 그림 참조
게임 구상은 다음과 같다.
if
조건문: 경우에 따라 다른 행동 지시while
반복문: 게임 종료 시까지 무한 반복random.choice
: 주사위 구현인터네서 검색을 통해 Turtle
모듈을 활용하여 만든 컴퓨터 게임을 쉽게 찾아볼 수 있다.
앞서 언급한 거북이 경주와 같이 매우 단순한 게임부터 보다 고급스런 게임까지
Turtle
모듈만으로도 훌륭한 게임을 구현할 수 있다.
참고자료 몇 개를 언급하면 다음과 같다.
Turtle
모듈을 활용한다.
다각형을 그리는 함수를 구현한다.
square
를 구현하기t
사용: 인자는 거북이 객체square
함수에 length
매개변수 추가length
의 인자값으로 지정
polygon
함수 구현하기
square
함수를 일반화하여 다각형 그리기n
사용.length
인 n
각형 그리기<그림 출처: wikipedia.org>
원과 호를 그리는 함수를 구현하라.
참조: Think Python: 인터페이스 설계
polygon
함수를 이용하여 원을 그리는 함수 circle
을 구현하라.t
: 거북이 인자r
: 반지름length * n
= 원둘레.
circle
함수를 수정하여 아래 조건을 만족하는 arc
함수를 구현하라.
angle
을 추가한다. angle
은 호(arc)를 그릴 때 사용되는 각도이다. angle = 360
이면 원을 그리게 된다.
<그림 출처: wikipedia.org)>
아래 그림의 도형을 그리는 함수들을 구현하라.
힌트: 모범답안을 담고 있는 파이썬 코드가
여기에
있음. 단, 앞 링크에 있는 코드는
이곳의
모듈을 불러와야 함.
아래 그림의 도형을 그리는 함수들을 구현하라.
힌트: 모범답안을 담고 있는 파이썬 코드가
여기에
있음.
아르키메데스 와선(spiral)을 그리는 함수를 구현하라.
<그림 출처: wikipedia.org>
힌트: 모범답안을 담고 있는 파이썬 코드가 여기에 있음.