객체 지향 프로그래밍
지금까지 프로그램을 작성할 때 , 우리는 데이터를 다루는 명령들의 블록인 함수들의 조합으로 프로그램을 구성하였다.
이러한 설계 방식을 절차 지향 프로그래밍 기법이라고 부른다.
이와달리 데이터와 기능을 객체라고 불리는 것으로 묶어서 프로그램을 구성하는 또 다른 기법이 있다.
대부분의 시간동안 절차 지향 프로그래밍 기법을 통해 프로그램을 작성하게 되겠지만 ,
큰 프로그램 , 복잡한 프로그램등을 작성할 때나 이 기법을 이용하는 것이 더 편리한 문제를 해결해야 할 경우
객체 지향 프로그래밍 기법을 활용할 수 있다.
객체 지향 프로그래밍 기법에는 클래스와 객체라는 두 가지 주인공이 있다.
클래스는 새로운 형식을 정의하는 것이며 , 객체는 클래스의 인스턴스를 의미한다.
이것을 다시 표현하면 우리가 int 라는 형식의 변수를 만들 수 있다는 것으로 , 이것은 곧 정수형을 저장하는 변수는
int 클래스의 인스턴스(객체)를 변수에 할당하는 것 이라고도 말할 수 있다.
( 파이썬에서는 정수형조차도 객체로 다루어진다. (int 클래스의 객체) )
객체는 그 객체에 내장된 일반적인 변수들을 사용하여 데이터를 저장할 수 있다.
이때 개체 혹은 클래스에 소속된 변수들을 필드(Field) 라고 부른다.
객체는 또한 내장된 함수를 이용하여 어떤 기능을 갖도록 할 수 있는데 , 이것을 클래스의 메소드(Method) 라고 부른다.
이러한 명칭을 구별하여 부르는것이 중요한데 , 이는 일반적인 변수와 함수와 달리 이들은 클래스나 객체에 소속되어 있는 대상들이기 때문이다.
또 , 이러한 필드와 메소드들을 통틀어 클래스의 속성(Attribute) 이라고 부른다.
필드는 크게 두가지 종류가 있다 , 하나는 클래스의 인스턴스/객체에 내장되어 있는것이고 , 또 하나는 클래스 자체에 내장되어 있는 것이다.
각각을 인스턴스 변수와 클래스 변수라 부른다.
( 인스턴스 변수 : 클래스의 인스턴스 / 객체에 내장되엉 있는 변수 , 클래스 변수 : 클래스 자체에 내장되어 있는 변수 )
클래스는 class 키워드를 통해 생성되며 클래스의 필드와 메소든느 그 아래 들여쓰기 된 블록에 차례로 정의된다.
self에 대하여
클래스 메소드는 일반적인 함수와 다른점이 있다.
그것은 메소드의 경우 매개변수의 목록에 항상 추가로 한개의 변수가 맨 앞에 추가되어야 한다는 점이다.
또한 메소드를 호출할 떄 이 변수에는 우리가 직접 값을 넘겨주지 않으며 , 대신 파이썬이 자동으로 값을 할당한다.
이 변수에는 현재 객체 자신의 참조가 할당되며 , 일반적으로 self 라 이름짓는다.
변수의 이름은 마음대로 지을수 있지만 , self 라는 이름을 사용하자 .
이것은 일종의 약속이며 다른 이름을 사용하는 것은 여러모로 불편함을 겪을 것이다.
'self'라는 표준적인 이름을 사용하면 우리의 프로그램을 읽는 사람들로부터 이것이 바로 그 변수 ( 클래스 메소드의 첫 매개변수) 임을 쉽게 알아보게 할 수 있고 , 특별한 IDE (Intergrated Development Environment)를 사용하는 사람들도 이를 쉽게 알아볼 수 있는 등 여러 장점이 있다.
파이썬이 self에 어떻게 값을 할당하는 것인지 그리고 정말 값을 직접 할당한 필요가 없는지 궁금할 것이다.
이해를 돕기위해 예를 하나 들어보자!
우리가 Myclass 라는 클래스를 생성했고 , 이 클래스의 객체를 myobject 라는 이름으로 생성했다고 해보자.
이제 이 객체의 메소드를 호출할 때는 myobject.method(arg1 , arg2)와 같이 하며 ,
이것은 파이썬에 의해 자동적으로 Myclass.method(myobject, arg1, arg2) 의 형태로 바뀌게 된다.
이것이 self의 모든것이다.
또한 이것은 아무런 인수도 넘겨받지 않는 메소드를 정의할 때도 , self 라는 하나의 인수를 추가해 주어야한다는걸 의미한다.
클래스
이해하기 쉽도록 간단한 클래스의 예시를 하나 들어보자.
class Person:
pass # An empty block
p = Person()
print(p)
실행 결과 :
<__main__.Person object at 0x014EB470>
class문을 사용하여 새로운 클래스 (Person)을 생성하였다.
그 아래로는 들여쓰기 된 새로운 블록이 시작되며 이 블록은 클래스의 몸체를 구성한다.
위 코드에서는 pass문으로 해당 블록이 빈 블록임을 나타냈다.
다음으로 , 이 클래스의 이름 뒤에 괄호를 열고 닫아주어 클래스의 객체/인스턴스를 만들었다.
(객체 초기화에 대해서는 추후에 정리하겠다.)
객체가 잘 생성되었는지 확인하기 위해 , 정의한 변수명을 입력하여 결과를 확인해본다.
그러면 이 객체는 main모듈의 Person 클래스의 인스턴스임을 알 수 있다.
메소드
앞서 , 클래스 / 객체는 메소드를 가질 수 있으며 , 메소드는 추가된 self 변수를 제외하고 함수와 똑같다는 것에 대해 얘기헀다.
아래는 예제다.
class Person:
def say_hi(self):
print("Hello, How are you?")
p=Person()
p.say_hi()
실행 결과:
Hello, How are you?
우선 그 중 init 메소드에 대해 알아보자.
init 메소드는 클래스가 인스턴스화 될 때 호출된다.
따라서 , 이 메소드는 객체가 생성될 때 여러가지 초기화 명령들이 필요할 때 유용하게 사용된다.
여기서 init의 앞과 뒤에 있는 언더바는 두번씩 입력해야한다.
class Person:
def __init__(self,name):
self.name = name
def say_hi(self):
print("Hello, my name is",self.name)
p = Person("Swaroop")
p.say_hi()
실행 결과 :
Hello, my name is Swaroop
먼저 매개변수 name을 넘겨받는 init 메소드를 정의한다. (물론 self를 포함하여 정의한다.)
그리고 , name이라는 필드를 생성한다.
이때 두 다른 변수의 이름으로 name 이라는 동일한 이름을 지정해주었음을 주목하자.
이것이 문제가 되지 않는 이유는 하나는 "self"라는 개체에 내장된 것으로써 self.name의 형태로 사용되며
또 하나는 name은 지역 변수를 의미하는 것으로 사용되기 때문이다.
프로그램 상에서 완전히 구분이 가능하기 때문에 혼란이 일어나지 않는다.
위 예제에서 가장 중요한건 , 우리가 init 메소드를 직접 호출해주지 않고 클래스로부터 인스턴스를 생성할 때 괄호 안에 인수 ( "Swaroop" ) 를 함께 넘겨주었다는 점이다.
이 점이 이 메소드가 특별히 다뤄지는 이유다.
이제 , say_hi메소드에서 처럼 객체 내부에서 self.name 필드를 사용할 수 있다.
'Programming > Python' 카테고리의 다른 글
상속 (0) | 2017.11.13 |
---|---|
클래스 변수와 객체 변수 (0) | 2017.11.13 |
문자열 보충설명 (0) | 2017.11.11 |
집합 그리고 참조 (0) | 2017.11.11 |
열거형 (0) | 2017.11.11 |