클래스란 함수나 변수들을 모아놓은 집합체이다. 하지만 단순한 데이터 자료형이라고 하기에는 활용도가 상당히 크다. 클래스를 어떻게 설계하냐에 따라서
프로그램의 명확성이 달라진다. 아래는 클래스의 기본적인 문법이다.
class 클래스명:
<수행할 문장 1>
<수행할 문장 2>
<수행할 문장 3>
<. . .>
좀 더 쉽게 설명하자면 다음과 같이 아주 기본적인 형태의 클래스를 선언한다.
class basic:
pass
위의 basic 이라는 클래스는 아무런 기능도 가지 않는 클래스이다. 하지만 기능이 없더라고 인스턴스 라는 것을 생성하는 기능은 있다.
인스턴스는 객체와 동일한 말이다. 즉, 클래스에 의해서 생성된 객체를 인스턴스라고 부른다
인스턴스
인스턴스는 클래스에 의해서 만들어진 객체로 한개의 클래스는 n개의 인스턴스를 만들어 낼 수 있다. 위에서 많든 클래스를 이용해서 인스턴스를
만드는 방법은 다음과 같다.
a = basic()
바로 basic()의 결과값을 돌려 받은 a가 객체이자 인스턴스이다. 함수를 사용해서 그 결과값을 받는 것과 비슷한 구조이다.
클래스 변수
* 이해를 돕기 위해 cmd 창에서 작성
위에서 클래스 이름은 Google이다. 우리는 위의 Google 클래스를 어떤 유용한 정보를 제공해주는 업체라고 가정한다.
이 업체는 가입한 고객에게만 특정한 정보를 제공하려고 한다. 가입을 하는 방법은 다음과 같다.
위 처럼 하면 python 이라는 아이디를 통해 업체인 Google클래스를 이용할 수 있다.
이제 python 아이디로 Google클래스가 제공하는 정보를 얻어내보자.
아이디 이름에다가 Google클래스가 제공하는 ser 변수를 '.'를 이용하여 호출했더니 "Hello Python" 이라는 정보를 얻게 되었다.
클래스 함수
Google은 이제 막 창업된지 얼마 되지 않아서 오직 ser이라는 정보 하나만 제공해 주고 있다. 하지만 제공해주는 정보의 양이 너무 없는 듯 하여
계산기 기능 중 더하기 서비스를 하기로 했다.
다시 Google 클래스를 선언한다. 물론 sum 함수에 의해 이젠 더하기 값을 돌려준다.
다시 python 이라는 아이디를 만들고 더하기 기능을 이용한다.
이젠 서비스 업체인 Google의 입장에서 생각해보자. 구글은 가입한 사람에게만 서비스를 제공하고 싶어한다. 이를 위해서 더하기 서비스에
약간의 트릭을 추가했는데 더하기 함수를 잘 보면, 첫 번째 입력 값으로 self라는 것을 집어넣었다.
누군가 다음처럼 더하기 서비스를 이용한다고 가정하자.
이렇게 하면 python 이라는 아이디를 가진 사람이 이 구글의 sum 서비스를 이용하겠다고 요청을 한다는 것이다. 위와 같이 했을 때 구글의
더하기 함수(sum)은 다음과 같이 인식한다.
누군가 서비스를 요청하니, 서비스를 먼저 해주기 전에 이 사람이 가입한 사람인지 아닌지 판단을 해야겠군. 첫 번째 입력 값으로 python이
들어오니 아이디를 가진 사람이네. 서비스를 해줘야겠다
다시 sum 함수를 살펴보자.
sum 함수는 첫 번째 입력 값으로 self 라는 것을 받고, 나머지로 더할 숫자를 받는다. 즉, 위에서 문법상 보면 python 아이디는 다음과 같이 sum 함수를
호출해야 한다.
python.sum(python, 1, 1)
sum 함수는 첫 번째 입력값으로 가입의 유무를 판단하는데, 문제는 위처럼 sum 함수를 호출하게 되면 python이 중복되어 사용된다.
따라서 파이썬에서는 self라는 개념을 이용하여 굳이 위의 방식에서 python을 뺀, 오직 더할 숫자만 입력해도 되게 해놓았다.
" python.sum(1, 1)이 호출되면 self는 호출시 이용했던 인스턴스(아이디 python)으로 변경된다.
self 이해하기
가입을 한 사람들이 구글에게 이제 계산기를 서비스 할 때 "Python님 1+2=3" 이런 식으로 자신의 이름을 넣어달라고 요청했다.
그래서 구글은 다시 Google클래스를 업그레이드 하기에 이르렀다. 이름을 입력받아서 sum 함수를 제공할 때 앞 부부에 그 이름을
넣어주기로 했다.
이제 사람들은 아래와 같이 이용 할 수 있다.
py 라는 아이디를 생성하고, 이름을 Hacker로 지정한 후 더하기 서비스를 이용한다.
다시 서비스 제공 업체인 구글의 입장에서 생각해보자. 우선 setname 변수를 살펴 보자.
py = Google() // py라는 아이디를 부여 받은 사람이
py.setname("Hacker") // 이름을 설정하겠다고 요구를 하였다.
위와 같은 상황이 발생하면 구글의 setname 함수는 다음과 같이 생각한다.
위의 기능이 바로 self 이다.py라는 아이디를 가진 사람이 자신의 이름을 "Hacker"로 설정하려고 하네. 그러면 앞으로 py 아이디로 접근하면 이 사람의 이름이 "Hacker"라는
것을 잊으면 안 되겠다
일단 py라는 아이디를 가진 사람이 Hacker 라는 이름을 setname 함수에 입력으로 주면 다음의 문장이 수행된다.
self.name = name
self는 첫 번째 입력 값으로 py 라는 아이디를 받기 때문에 다음과 같이 이해할 수도 있다.
py.name = name
name은 두 번째로 입력받은 "Hacker" 이라는 값이므로 위의 문장은 다시 다음과 같이 변한다.
py.name = "Hacker"
즉, py라는 아이디를 가진 사람의 이름은 이제 항상 Hacker 라는 말이다. 이제 아이디 py에 이름을 부여하는 과정은 끝이다.
다음은 "이름, 연산 과정 및 결과" (Hacker, 1+1=2) 라는 서비스를 가능하게 해주는 함수를 보자.
1+1 = 2 라는 서비스만을 제공했던 이전과 달리 지금은 self.name을 이용하여 이름을 추가하여 출력한다.
우선 sum 함수를 이용하기 까지의 과정은 다음과 같다.
py 라는 아이디를 가진 사람이 이름을 Hacker로 설정하고 sum 함수를 요청하였다.
이 때 서비스 제공 업체 Google의 sum 함수는 다음과 같이 생각한다.
py라는 아이디를 가진 사람이 더하기를 이용하네. 우선 아이디가 있으니깐 가입한 사람은 맞고 음.. 이름은 Hacker 군아.
좋아 그럼 이제 연산을 하고 이름을 앞에 넣어주고 결과 값을 돌려줘야겠다
여기서 우리가 알아야 할 사항은 "sum 함수가 어떻게 py 라는 아이디를 가진 사람의 이름을 알아내는가?" 이다.
먼저 setname 함수에 의해 'Hacker' 라는 이름을 설정하였기 때문에 setname 함수에 의해서 py.name 이란 것이 "Hacker"라는 값을 갖게 되었다.
따라서 sum 함수에서도 self.name은 py.name으로 치환, 즉 'Hacker' 값을 갖게 된다.
__init__ 함수 ??
위에서 구글이 제공하는 sum 함수는 치명적인 오류가 있다. 바로 이름을 설정하지 않고 바로 sum 함수를 호출했을 때의 경우이다.
위와 같이 하면 test.setname("이름이 없엉") 와 같은 과정이 생략되었기 때문에 에러가 나는 것이다.
그래서 구글은 또 다시 클래스를 수정하기로 했다. 지금까지는 사람들이 서비스 가입 시 바로 아이디를 주는 방식이었다.
그러나 이제부터는 아이디를 줄 때 그 사람의 입력을 받아야만 아이디를 주기로 하였다. 그렇다면 test.setname 과정이 생략되기 때문이다.
위와 같은 방법을 찾던 중 구글의 개발자가 __init__ 함수를 이용하자고 제안하였다. __init__함수는 초기화 함수라고도 불리우는 함수이다.
이를 적용한 클래스는 다음과 같다.
위의 Google클래스를 이전의 클래스와 비교해 보면 바뀌 부분은 setname 함수의 이름인 setname이 __init__으로 바뀐것이다.
__init__함수의 의미는 다음과 같다.
인스턴스를 만들 때 항상 실행된다
=> 즉, 위의 클래스에서는 아이디를 부여받을 때 항상 실행된다는 의미
따라서 이제 위의 서비스에 가입을 하기 위해서는 다음과 같이 해야 한다.
이전에는 test = Google()만 하면 되지만 이제는 __init__함수 때문에 test = Google("Hacker") 처럼 아이디를 부여받을 때 이름 또한 써줘야 한다.
클래스 상세 분석
다시 말하지만, 클래스란 함수나 변수 등을 포함하고 있는 일종의 집합체이다. 클래스의 함수는 일반적인 함수와 다르게 매우 다양한 용도로 쓰인다.
클래스는 프로그래머가 구현하는 것이며, 클래스 이용시 전역 변수를 쓸 필요가 겂어서 좋고 클래스에 의해 만들어진 인스턴스라는 것을 중심으로
코딩을 수행하기 때문에 객체지향 프로그래밍이 가능해진다.
클래스의 구조
위에서 보듯이 class 라는 명칭은 클래스를 만들 때 쓰이는 일련이 예약어이고 그 바로 뒤에는 클래스 이름을 지정해야 한다.
클래스 이름 뒤에 상속할 클래스가 있다면 상속할 클래스 이름을 명시하며, 클래스 내부에는 클래스 변수와 함수가 있다.
사칙연산 클래스
클래스의 이해를 돕기 위해 사칙연산을 하는 클래스를 만들것이다.
위와 같이 calc()라는 클래스에 미리 setdata를 이용하여 숫자 2개를 주고
t.sum을 호출하면 합계, sub()은 뺀 값 등 사칙연산을 수행하는 클래스를 만든다.
우선 위처럼 동작하는 클래스를 만들어야 한다. 제일 먼저 해야할 것은 t = calc() 처럼 인스턴스를 만들 수 있게 해야 한다.
위의 클래스는 아무런 변수나 함수도 포함되지 않지만 우리가 원하는 t = calc() 로 인스턴스 t를 만들 수 있는 기능이 있다.
아래에서 확인이 가능하다.
위에서 만든 인스턴스 t는 아무런 기능도 없다. 우리는 사칙연산을 수행할 인스턴스를 만들어야 하기 때문에 우선적으로 인스턴스 t에
더하기, 곱하기 등 연산을 수행할 때 사용할 2개의 숫자를 부여해야 한다. 이를 위해서는 아래와 같이 setdata를 구현한다.
클래스 내의 함수를 다른 말로 메소드라고 한다. 즉, setdata는 calc() 클래스의 메소드이다.
입력 인수로 self, first, second란 3개의 입력을 받는자. 하지만 일반적인 함수와 달리 클래스 내의 함수에서 1번째 입력 인수는 특별한
의미를 갖는다. 위에서 보면 바로 self가 특별한 의미를 갖는 변수이다.
위에서 보는 것처럼 인스턴스 f를 만든 다음에 t.setdata(11, 5)처럼 하면 calc 클래스의 setdata 함수가 호출되고 setdata함수의 1번째 인수에는
자동으로 t 라는 인스턴스가 입력으로 들어가게 된다.
즉, setdata의 입력 인수는 self, first, second 총 3개이지만 t.setdata(11, 5)처럼 2개의 입력 값만 주어도 t 라는 인스턴스가 setdata의 1번째 입력을
받는 변수인 self에 대입된다.
self : 인스턴스 t
fisrt : 11
second : 5
이제 더하기 기능을 포함한 클래스는 아래와 같이 만든다.
추가된 것은 sum 이란 함수이다. 입력으로 받는 값은 self 밖에 없고 돌려주는 값은 result이다.
t.sum() 처럼 하면 sum 함수에 자동으로 인스턴스 a가 1번쨰 입력 인수로 들어가는 것이다.
여기까지 이해하였다면 사칙연산은 새로운 함수와 연산 기호만 수정하면 되기 때문에 어려울 것이 없다.
코난 클래스
사칙연산 보다는 조금 더 재미있고 형태가 다른 코난 클래스를 만들 것이다.
클래스 이름은 conan 이다.
인스턴스는 anon이다.
nickname 함수
"명탐정" 출력
setname 함수
이름 설정
fullname 함수
닉네임을 포함한 전체 이름을 출력
case 함수
사건이 일어난 장소로 가는 함수
인스턴스를 만들 수 있는 클래스는 위와 같은 형태이다.
nickname은 클래스 변수이다. 이 클래스 변수 nickname은 Conan 클래스에 의해서 생성되는 인스턴스 모두에 nickname은 "명탐정" 이라는 값을
갖게 하는 기능이다. 위에서 보듯이 anon/test 모두 같은 닉넴임을 보유한다.
이름을 설정하기 위해 setname 함수를 사용한다.
위에서 보듯이 setname 함수에 "코난" 이란 값을 인수로 주어서 결국 self.fullname 에는 "명탐정 " + "코난" 이란 값이 대입된다.
위의 과정을 살펴보면 다음과 같다.
self.fullname = self.nickname + name ==> 2번째 입력 값 name은 "코난" 이므로 다음과 같이 바뀐다.
self.fullname = self.nickname + "코난" ==> 다음에 self는 setname 함수의 1번째 입력으로 들어오는 anon 라는 인스턴스로 바뀐다.
anon.fullname = anon.nickname + "코난" ==> anon.nickanem은 클래스 변수로 항상 "명탐정" 이란 값을 갖기 때문에 다음과 같이 바뀐다.
anon.fullname = "명탐정 " + "코난"
이제 우리의 목적에서 1가지 기능만 남아있다. 바로 사건 현장에 보내게 하는 것으로 함수 case를 사용하여 구현한다.
case란 함수를 추가시키고 입력 값으로 인스턴스와 place를 받는다. 그리고 해당 값들을 포맷 스트링을 이용하여 문자열에 삽입한 후 출력한다.
초기값 설정하기
위에서 Conan이라는 클래스를 이용해서 인스턴스를 만들었는데 이 인스턴스에 setname 함수를 이용해서 이름을 설정해 주는 방식으로 코딩하였다.
하지만 위에서 만든 함수를 다음과 같이 실행해보자.
>> anon = Conan()
>> anon.case("서울")
에러가 나게 된다. 에러의 이유는 case 함수에서 self.fullname 이란 변수를 필요로 하는데 self.fullname 이란 것은 setname 이란 함수에 의해서 생성되는
것이기 때문에 위의 경우 setname을 해주는 부분이 생략되어서 에러가 나게 되는 것이다. 따라서 이런 에러가 나는 것을 방지하기 위해서 anon 이라는
인스턴스를 만드는 순간 setname 함수가 동작하게 한다면 상당히 편리할 것이다. 이러한 생각으로 나온 개념이 __init__ 함수이다.
__init__함수, 초기치를 설정
setname 함수의 이름이 __init__ 로 바뀌었다. 이것의 차이점을 알고 싶다면 다음처럼 해보자.
위와 같은 에러 메시지를 볼 수 있다. 에러 메시지의 원인을 보면 입력 인수로 2개를 받아야 하는데 1개만 받았다는 에러이다. 여기서 1개를 받았다는 것은
바로 anon 이라는 인스턴스이다. 즉, __init__함수는 2개의 입력값을 요구한다. 간단히 "anon = Conan("서울")" 이런 식으로 2개의 입력값을 줄 수 있다.
__del__함수, 인스턴스가 사라질 때 호출
이번에는 인스턴스가 사라질 때 특정한 행동을 취할 수 있게 하는 방법에 대해 알아보자. 인스턴스가 사라진다 함은 다음과 같은 경우이다.
파이썬이 자체적으로 가지고 있는 내장 함수 del에 의해서 anon이라는 인스턴스를 소멸 시킬 수 있다. 또한 파이썬 프로그램이 다 수행되고 종료될 때 역시 만들어진 인스턴스들은 모두 사라진다.
위와 같이 클래스를 구현한 다음 아래와 같이 실행해보자.
즉, 클래스 내에 사용되는 __del__ 이란 함수는 인스턴스가 사라질 때 호출되는 것임을 확인할 수 있다.
상속
상속이란 '물려받다'라는 뜻으로 재산 상속의 상속과 같은 의미이다. 파이썬은 객체 지향 코딩이 가능하기 때문에 이 개념을 사용할 수 있다. 어떤 클래스를
만들 떄 다른 클래스의 기능을 상속받을 수 있는 것이다. 우리는 Conan 이란 클래스를 만들었는데 이번엔 Culprit 이란 클래스를 만들어 보자.
상속의 개념을 이용하면 다음과 같이 간단하게 할 수 있다.
닉네임을 "수상한 " 으로 바꾸고 아무것도 하지 않았다. 이제 아래와 같이 해보자.
보는 바와 같이 Conan 클래스의 모든 기능을 상속 받았음을 확인 할 수 있다. 이걸 이용하면 별의별 클래스를 쉽게 만들 수 있다.
상속의 개념 중 하나 더 알아두면 좋은 것은 상속 대상이 된 클래스의 함수 중에서 그 기능을 달리 하고 싶을 때가 있다. 즉, 위의 예에서
"수상한 용의자, 사건이 일어난 서울 시청으로 간다" 라는 것은 조금 이상하니 "서울 시청 근처 어딘가에 숨는다" 이런 식으로 바꿀 때이다.
위와 같이 출력되게 끔 Culprit를 수정하면 아래와 같다.
위처럼 case 함수를 다르게 설정하면 된다.
연산자 오버로딩
연산자 오버로딩이란 연산자 (+, -, *, /, 등)를 인스턴스끼리 사용할 수 있게 하는 기법을 말한다. 쉽게 말해서 다음과 같은 것을 가능하게 한다.
t1 = Conan("코난")
t2 = Culprit("용의자")
t1 + t2
"명탐정 코난, 수상한 용의자를 추궁하다"
우선 이미 만들었던 클래스에 몇가지 기능을 추가시킨다.
위의 프로그램의 실행 부분인 마지막 4줄을 보자.
anon = Conan("코난")
test = Culprit("용의자")
anon.ask(test)
anon + test
먼저 anon = Conan("코난")으로 anon 이라는 인스턴스를 만들고 test 라는 인스턴스 역시 생성한다. 그 다음 anon.ask(test)이란 메소드 aks가 호출된다.
ask 메소드를 보면
def ask(self, suspect):
print "%s, %s를 추궁한다" %(self.fullname, suspect.fullname)
입력으로 2개의 인스턴스를 받는다. 따라서 anon.ask(test)와 같이 호출하면 self에는 anon이 들어가고 suspect에는 test가 들어간다.
따라서 "명탐정 코난, 수상한 용의자를 추궁한다" 라는 문장이 출력된다.
이제 "anon+test" 문장이 실행되는데, 더하기 표시기호인 '+'를 이용해서 인스턴스를 더하려고 시도한다. 이렇게 '+' 연산자를 인스턴스에 사용하게 되면
클래스의 __add__라는 함수가 호출된다.
def __add__(self, suspect):
print "%s, %s를 의심한다" %(self.fullname, suspect.fullname)
anon + test 처럼 호출되면 __add__(self, suspect) 함수의 self는 anon이 되고 suspect는 test가 된다.
따라서 "명탐정 코난, 수상한 용의자를 의심한다" 라는 문장이 출력된다.
'Developing > Python_배우기' 카테고리의 다른 글
Python 11 - 예외처리 (0) | 2014.02.15 |
---|---|
Python 10 - 모듈 (1) | 2014.02.03 |
Python 08 - 입/출력 (I/O) (0) | 2014.01.25 |
Python 07 - 함수 (0) | 2014.01.12 |
Python 06 - 제어문 (for) (0) | 2014.01.12 |