클래스와 객체지향 프로그래밍
클래스는 리스트나 딕셔너리 처럼 데이터를 편하게 관리하기 위해 고안된 도구입니다. 그 성능이 워낙 강력해서 패러다임이 등장하기까지 했습니다. 클래스를 이용하여 프로그래밍하는 패러다임을 '객체지향 프로그래밍'이라고 합니다. 물론 클래스를 이용해야만 객체지향프로그래밍이 되는 것은 아닙니다. 객체지향은 더 포괄적인 개념이긴 한데, 좁은 의미로 쉽게 이해하면 클래스를 이용한 프로그래밍이라고 할 수 있습니다.
<좁은 의미의 이해>
객체 지향 프로그램 = 클래스를 이용한 프로그래밍
넓은 의미의 객체지향 프로그래밍은 모든 것을 '객체'로 보고 프로그래밍 하겠다는 것입니다. 프로그래밍을 객체와 객체의 상호작용으로 생각하는 것입니다. 뭐든 넓은 의미는 이해가 어렵습니다. 백터의 좁은 의미가 '크기와 방향을 가진 물리량'인데 반해, 넓은 의미는 '벡터 공간의 원소' 인 것과 비슷합니다. 의미가 넓어질 수록 추상적이라 이해가 어렵습니다. 일단은 객체지향프로그래밍을 좁은 의미로 이해하고 의미를 넓혀나가는 것이 좋습니다. 클래스를 사용하고 나서 무엇이 편해졌는지를 알게 되면 객체지향프로그래밍에 대해서도 감을 잡을 수 있을 겁니다.
그래서 클래스가 무엇인가?
클래스가 무엇인지 처음 들어본 분들은 위 내용을 읽고 어리둥절하실 겁니다. 클래스가 뭔지도 모르는데 객체지향은 뭘 어쩌라는 건가 싶을텐데요. 다시 클래스로 돌아가봅시다. 클래스는 데이터를 편하게 관리하기 위해 고안된 도구입니다.
'너 코딩하기 편하라고 만든거야'
네 맞습니다. 코딩 인생은 클래스를 알기 전과 후로 나뉘게 됩니다. 클래스는 그 만큼 편하고 유용합니다. 매력적이기 까지 한데요. 어떤 상황을 객체지향으로 프로그래밍하려고 고민하는 과정 자체가 상당히 재밌습니다. 그래서 클래스가 뭔데? 라는 질문에는 짧은 대답과 긴 대답이 있는데요. 짧은 대답을 먼저 하고 나서 긴 대답을 하겠습니다.
'클래스는 객체를 생성하기 위해 변수와 메소드를 미리 정의해놓은 템플릿입니다.'
클래스는 마치 붕어빵틀과 같습니다. 붕어빵의 모양을 정의해 놓은 틀입니다. 원하는 재료를 부어서 붕어빵이라는 객체를 만들 수 있습니다. 막연하죠? 클래스를 제대로 이해하려면 클래스를 직접 사용해봐야 합니다. 클래스가 무엇인지 이해하고 나면 붕어빵틀 예시가 비로소 이해될 겁니다. 그래서 늘 생각합니다. 대체 이 붕어빵 예시가 무슨 소용이 있는걸까.
자, 클래스가 무엇인가에 대한 긴 설명입니다.
예시 소개
한 가지 상황을 설정하겠습니다. 이 상황을 클래스 없이 해결해보고, 클래스를 이용하여 해결해보겠습니다. 두 결과를 비교하면 클래스가 얼마나 유용한지 알게 되실겁니다.
우리는 헬스장을 운영하고 있습니다. 헬스장 회원관리 프로그램을 만들고 싶습니다. 우리가 입력하려는 회원 정보의 종류는 아래와 같습니다.
'이름, 나이, 키, 몸무게, PT_잔여_횟수'
구현하고 싶은 기능은 아래와 같습니다.
'PT를 받을 때마다 잔여 횟수 차감'
회원 세명이 등록했습니다. 회원정보는 아래와 같습니다.
김지연, 23, 165, 62, 10회
박광선, 33, 181, 77, 5회
홍연지, 25, 155, 55, 30회
클래스 없이 구현해보기
회원 세명의 정보는 아래와 같이 딕셔너리를 이용하여 등록할 수 있습니다. 클래스를 공부하시는 분들이니까. 딕셔너리 정도는 알고 계시겠죠? 딕셔너리가 무엇인지 모르시는 분들은 먼저 리스트, 튜플, 딕셔너리 정도는 공부하고 클래스에 도전합시다.
member1={'이름':'김지연','나이':23,'키':165,'몸무게':62,'PT_잔여_횟수':10}
member2={'이름':'박광선','나이':33,'키':181,'몸무게':77,'PT_잔여_횟수':5}
member3={'이름':'홍연지','나이':25,'키':155,'몸무게':55,'PT_잔여_횟수':30}
member1,member2, member3을 '회원변수'라고 부르겠습니다. 이번에는 PT 잔여횟수를 차감하는 기능을 구현해봅시다. 함수를 정의할건데요. 함수에 회원변수를 입력하면 PT 잔여횟수가 차감되도록 만들어 봅시다. 잔여횟수가 0회인 회원의 변수가 입력되면 '잔여 횟수가 없습니다'라는 메시지를 출력하도록 해봅시다.
member1={'이름':'김지연','나이':23,'키':165,'몸무게':62,'PT_잔여_횟수':10}
member2={'이름':'박광선','나이':33,'키':181,'몸무게':77,'PT_잔여_횟수':5}
member3={'이름':'홍연지','나이':25,'키':155,'몸무게':55,'PT_잔여_횟수':30}
#잔여횟수 차감 함수
def PT(member) :
if member['PT_잔여_횟수']==0 :
print("잔여 횟수가 없습니다")
else :
member['PT_잔여_횟수']=member['PT_잔여_횟수']-1
작동을 잘 하는지 확인해봅시다. 김지연씨가 PT를 한번 이용하면 아래와 같이 함수를 사용하면 됩니다. 차감이 잘 되는 것을 알 수 있습니다.
>>> PT(member1)
>>> member1['PT_잔여_횟수']
9
클래스로 구현해보기 (1.회원객체 만들기)
클래스를 만들고 클래스를 이용하여 회원객체들을 만들어봅시다. 객체가 뭐야? 라는 의문이 드실 수도 있을 것 같네요. 이 대목에서 객체는 붕어빵틀을 이용해서 찍어낸 붕어빵들입니다. 오, 붕어빵 예시가 꽤 유용하네요. (객체의 넓은 의미는 '모든 대상'입니다. 걍 모든게 다 객체에요)
코드는 아래와 같습니다. 코드를 천천히 뜯어보며 이해해 봅시다.
#회원이라는 붕어빵을 찍어낼 붕어빵틀 정의
class PT_member :
def __init__(self,name,age,height,weight,coupon):
self.name=name
self.age=age
self.height=height
self.weight=weight
self.coupon=coupon
#회원객체 반들기 (붕어빵 찍어내기)
member1=PT_member('김지연',23,165,62,10)
member2=PT_member('박광선',33,181,77,5)
member3=PT_member('홍연지',25,155,55,30)
class 뒤에 PT_member 는 클래스 이름입니다. 붕어빵틀의 이름이라고 생각하시면 됩니다. def 는 함수선언 명령어입니다. 클래스 안에서 __init__라는 함수를 정의하고 있는데요. 일반적으로 함수에는 원하는 이름을 사용할 수 있는데, 클래스에서 정보를 입력받는 함수는 이름이 정해져 있습니다. __init__ 이라는 이름입니다. initialize 의 약어이고 '초기화'라는 뜻입니다. 클래스를 이용하여 객체를 만들 때 값들을 입력받아 초기화할 때 사용하는 함수입니다. __init__ 을 사용하기로 약속한 것이지 뭐 대단한 의미가 있는건 아닙니다. 함수에 입력된 값들을 봅시다. name, age, height, weight, coupon 은 우리가 받기로 한 정보들입니다. 여기까지는 어렵지 않죠? 그런데 self 가 보입니다.
self를 설명하기 위해 member1 선언된 줄을 봅시다. 괄호 안에 입력된 값들을 보면 이름, 나이,키, 몸무게, 잔여횟수만 입력되어 있지 self에 해당되는 값은 없습니다. self에는 무엇이 입력되는걸까요? member1 이라는 객체를 생성할 때, self에는 member1 이라는 이름이 입력됩니다. member1 을 선언하는 순간 __init__ 함수의 self 자리에 member1 이 입력되고, 정보들은 아래와 같은 형태로 저장됩니다.
member1.name='김지연'
member1.age=23
member1.height=165
member1.weight=62
member1.coupon=10
정말 그러한지 확인해봅시다.
>>> member1.name
'김지연'
>>> member1.age
23
>>> member1.height
165
>>> member1.weight
62
>>> member1.coupon
10
정말 그렇죠? 위와 같이 정의해 놓으면 각 자료에 접근하기가 정말 편합니다. 편하게 자료에 접근하는 구조를 만들기 위해서 self 를 등장시킨 것입니다. 이정도 이해한 뒤 클래스를 정의한 코드를 보면 쌩뚱맞게 self 를 왜 등장시킨 것인지 이해가 될 겁니다.
이번에는 PT를 한 번 받으면 잔여 횟수 값이 차감되는 기능을 구현해봅시다.
클래스로 구현해보기 (2.차감 기능 추가하기)
PT를 한번 받으면 잔여 횟수가 차감되는 기능을 구현할 것인데요. 역시나 클래스 안에 구현할 겁니다. 클래스로 시작해서 클래스로 끝내는 것이죠. 아래와 같이 구현합니다.
class PT_member :
def __init__(self,name,age,height,weight,coupon):
self.name=name
self.age=age
self.height=height
self.weight=weight
self.coupon=coupon
#PT 받으면 횟수 차감하는 메소드
def use_coupon(self) :
self.coupon=self.coupon-1
클래스 안에 use_coupon 이라는 함수를 정의했습니다. 클래스 안에 정의된 함수는 특별히 '메소드'라고 부릅니다. 역시나 self가 사용되었습니다. 예를 들어 member1 이라는 회원객체를 만들었다고 합시다. 이때 use_coupon 이라는 메소드를 작동시키면 member1.coupon 에 저장된 값이 1 차감되는 것입니다.
그렇다면, use_coupon 이라는 메소드는 어떻게 사용할까요? 아래와 같이 사용합니다. 꼭 괄호를 넣어주셔야 합니다.
member1.use_coupon( )
잘 작동하는지 확인해봅시다.
>>> member1.coupon
10
>>> member1.use_coupon()
>>> member1.coupon
9
잘 작동합니다.
간단한 예시를 이용하여 클래스를 설명드렸는데요. 클래스의 장점이 잘 와닿게 만들어 드리고 싶었는데, 예시가 단순해서 클래스의 장점이 와닿지 않을까 걱정이 됩니다. '그냥 딕셔너리로 해도 비슷한거 아냐?' 이런 의문이 드시면 안될텐데 걱정입니다.
다시 한번 말씀드리지만 '객체지향'은 새로운 패러다임이 생길 정도로 아주 유용한 방법이니까요. 클래스에 익숙해지셔서 객체지향스타일로 프로그램이하시기를 추천드립니다. 객체지향을 정말 단순한 한마디로 요약하고 글을 맺겠습니다.
'다른 방법으로도 할 수 있지만, 굳이 클래스로 다 해보려고 하는 것'
일단은 이정도 이해로 시작해 보시고, 나중에 더 깊이 이해하시길.
'10. 클래스(class) > 기초' 카테고리의 다른 글
[파이썬 클래스] 원본 변수가 바뀌는 경우 해결 (copy 함수를 사용해야 하는 이유) (0) | 2023.05.25 |
---|---|
[파이썬] 클래스 정의할 때 self 대신 다른 이름를 써도 될까 (0) | 2023.05.12 |
[파이썬] 클래스에 정의된 인스턴스 변수 보는 법 (vars) (0) | 2023.05.11 |
[파이썬] 문자열도 클래스다 (리스트,튜플,딕셔너리도) (0) | 2023.05.11 |
[파이썬] 클래스 만드는 방법 (0) | 2023.05.11 |
댓글