Python 기본 - 9. 클래스 쉽게 다루기

클래스는 우리의 단순 노동 작업을 크게 줄여주고, 코드를 깔끔하게 해 주는 효자다.

클래스붕어빵 틀이다. 일종의 틀로, 똑같은 무언가를 만들어 낼 수 있는 도면과 같은 것이다.

객체는 클래스라는 틀에 의해 생성된 구체적인 어떤 것을 칭한다.

붕어빵 틀은 클래스, 만들어진 붕어빵은 객체

간단하게 예제를 통해서 클래스의 기본 구조에 대해 먼저 이해해 보자.

1
2
3
4
5
6
7
8
9
10
11
12
class FourCal:    # 클래스명 "FourCal" 선언
def setdata(self, first, second): # 매개변수 선언
self.first = first
self.second = second

>>> a = FourCal() # 객체 "a" 생성 (FourCal의 인스턴스)
>>> a.setdata(4,2) # 입력값 4와 2 전달

>>> print(a.first)
4
>>> print(a.second)
2

파이썬에서 클래스를 다룰 때, 매개변수에 self를 포함시켜야 함에 주의하자.

아래의 그림을 보면 그 구조를 파악하기 쉬울 것이다. 참고 : 파이썬 위키

객체와 호출 입력값의 전달 구조

이제 이 기본 지식으로 하나하나 클래스를 구현해 볼 것이다.

지금부터 내가 게임 개발자라고 가정해 보자. 다음과 같은 임무가 주어졌다.

  • 기사, 마법사, 궁수 캐릭터를 만들어라.
  • 각각의 캐릭터는 레벨, 이름, HP가 있다.
  • 각각의 캐릭터는 좌우, 앞뒤로 움직일 수 있다.
  • 각각의 캐릭터는 공격을 할 수 있다.
  • 마법사는 마법을 쓸 수 있다.

먼저 기사 클래스부터 만들어 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Knight:
level = 20
name = "Battery"
hp = 200

def move(self, direction):
print(direction + "방향으로 이동합니다")

def attack(self):
print(self.name + "이(가) 공격합니다")

>>> knight1 = Knight() # knight1 객체 선언 (클래스명 Knight의 인스턴스)

>>> print(knight1.level, knight1.name, knight1.hp)
20 Battery 200

>>> knight1.move("왼쪽")
왼쪽방향으로 이동합니다

>>> knight1.attack()
Battery이(가) 공격합니다

위에서 level, name, hp 등의 클래스 안에서 변수를 지정하는 것을 클래스 변수 라고 한다. 멤버 변수라고도 부른다.

위 코드에 따르면, Knight 클래스에 의해서 생성된 인스턴스들은 기본적으로 지정된 클래스 변수 값을 가진다.

기사 직업을 가진 유저가 어디 한둘 이겠는가? 객체를 생성할 때 바로바로 클래스 변수를 설정할 수 있도록 객체 변수를 설정해 보자.

init() 은 객체를 생성할 때 호출되는 함수이다.

여러가지 클래스 변수들을 객체가 생성될 때 설정할 수 있게 해준다.

이번에는 기사 말고 마법사 클래스를 객체 변수를 사용하여 예시로 만들어보자.

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
class Wizard:
def __init__(self, level, name, hp): # 4개의 객체 변수 지정
self.level = level
self.name = name
self.hp = hp

def move(self, direction):
print(direction + "방향으로 이동합니다")

def attack(self):
print(self.name + "이(가) 공격합니다")

def magic(self):
print(self.name + "이(가) 마법을 사용합니다")

>>> wizard1 = Wizard(30, Bloodtrail, 150) # wizard1 객체 생성

>>> print(wizard1.level, wizard1.name, wizard1.hp)
30 Bloodtrail 150

>>> wizard1.move("위쪽")
위쪽방향으로 이동합니다

>>> wizard1.attack()
Bloodtrail이(가) 공격합니다

>>> wizard1.magic()
Bloodtrail이(가) 마법을 사용합니다

코드를 짜다보니 앞서 작성한 기사 클래스와 겹치는 부분이 많다. (짜증)

그리고 이렇게 각각의 클래스를 작성하면, 객체 변수를 하나 추가하고 싶을 경우 클래스 3개를 수정해야 하는 불상사가 발생하게 된다..

지금은 클래스가 3개라서 다행이지만, 만약 클래스가 100개라면?

이런 경우, 우리는 상속이 추가된 클래스 구조를 생각해야 한다.

상속이란, 부모 클래스에 이미 구현되어진 클래스 변수와 함수를 자식 클래스가 받아서 사용하는 것을 의미한다.

위 예제 코드에서 반복되는 부분을 부모 클래스로 구성해 보자.

1
2
3
4
5
6
7
8
9
10
11
class Character:
def __init__(self, level, name, hp): # 반복되는 클래스 변수
self.level = level
self.name = name
self.hp = hp

def move(self, direction): # 반복되는 클래스 함수 1
print(direction + "방향으로 이동합니다")

def attack(self): # 반복되는 클래스 함수 2
print(self.name + "이(가) 공격합니다")

Character 이라는 클래스를 새로 만들고, 기사, 마법사, 궁수 클래스를 만들 때 공통적으로 포함되는 클래스 변수와 클래스 함수들을 집어 넣었다.

이제 이 부모 클래스를 사용해서 자식 클래스를 구성해 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Knight(Character):    # 부모 클래스인 Character을 사용
pass

class Archer(Character):
pass

class Wizard(Character):
def magic(self):
print(self.name + "이(가) 마법을 사용합니다")

>>> knight_user = Knight(20, "Battery", 200)
wizard_user = Wizard(30, "Bloodtrail", 150)
archer_user = Archer(15, "CashIsK1ng", 100)

>>> knight_user.move("오른쪽")
오른쪽방향으로 이동합니다

>>> wizard_user.magic()
Bloodtrail이(가) 마법을 사용합니다

>>> archer_user.attack()
CashIsK1ng이(가) 공격합니다

클래스의 상속 관계를 잘 설정해 놓으면, 이렇게 깔끔하게 코드가 완성된다.

차후 MP, 마지막으로 접속한 시간 등의 변수를 추가할 때에도 부모 클래스인 Character만 수정하면 모든 자식 클래스에 제대로 적용될 것이다.

클래스 작성에 익숙해지자!