파이썬 클래스 이해하기

파이썬 클래스 이해하기

객체 지향 프로그래밍(OOP, or Object-Oriented Programming)은 개별 객체에 관련 특성과 동작을 묶어서 프로그램을 구성하는 방법이다.

개념상 객체는 시스템의 구성 요소와 같다. 프로그램을 일종의 공장 조립 라인이라고 생각해보자. 시스템 구성 요소 조립 라인의 각 단계는 일부 재료를 가공하고, 궁긍적으로 원재료를 완제품으로 변환한다.

객체는 데이터를 담는다. 마치 조립 라인 각 단계의 원자재나 사전에 가공된 재료처럼 말이다. 또한, 각 조립 라인의 구성 요소가 수행하는 동작과도 비슷하다.


클래스는 왜 필요한가

숫자, 문자열, 그리고 리스트와 같은 기본 자료구조는 무언가의 가격이나 시의 이름이라던지, 좋아하는 색과 같은 간단한 것을 나타내도록 설계되었다.

예를 들어, 조직의 직원들을 기록한다고 가정해보자. 그러기 위해서는 각 직원의 이름이나, 나이, 직함, 일을 시작한 해와 같은 기본 정보들을 저장해야 할 것이다. 이런 정보들을 다음과 같이 표현할 수 있다.

kirk = ["James Kirk", 34, "Captain", 2265]
spock = ["Spock", 35, "Science Officer", 2254]
mccoy = ["Leonard McCoy", "Chief Medical Officer", 2266]

하지만 이런 방식에는 몇 가지 문제가 있다.

첫 번째로, 리스트 kirk가 선언되고 나중에 kirk[0]과 같이 참조한다면, 아마도 몇 번째 요소에 직원의 이름이 담겨있는지 헷갈릴 수 있다. 심지어 모든 직원이 리스트에 동일한 수의 요소를 가지고 있지 않다면 어떻게 해야하는과 같은 고민을 할 수 있다.

두 번째로, 리스트 mccoy에는 나이가 빠져있다. 즉 mccoy[1]과 같이 호출한다면 McCoy의 나이가 아닌 "Cheif Medical Officer"를 반환할 것이다.

이런 유형의 코드를 더 잘 관리하고 유지할 수 있도록 만들어주는 좋은 방법이 클래스(class)를 사용하는 것이다.


클래스란 무엇인가

클래스는 사용자가 정의한(user-defined) 자료 구조를 생성하기 위해 사용된다. 또한 클래스는 클래스에서 생성된 객체가 해당 데이터로 수행할 수 있는 동작과 작업을 정의하는 메서드라고 불리는 특별한 함수를 가진다.

중요한 점은 클래스는 단지 구조를 제공한다는 것이다. 클래스는 무언가가 어떻게 정의되어야 하는지에 대한 청사진(blueprint)이라고 할 수 있다. 실제로 클래스는 실제 컨텐츠 자체를 제공하지 않는다. Dog이라는 클래스가 개를 정의하기 위해 이름이나 나이가 필요하다는 것을 명시할 수는 있지만, 실제로 특정 개의 이름이나 나이는 명시하지 않는다.

클래스 vs. 인스턴스

클래스를 청사진이라고 한다면, 인스턴스는 실제 데이터를 포함하는, 클래스에서 만들어진 객체이다. Dog 클래스의 인스턴스는 더 이상 청사진이 아닌, 예를 들어 Miles라는 이름의 이제 네 살이 된 실제 개이다.

다르게 이해하자면, 클래스는 양식이나 설문지와 같다. 왜냐하면 필요한 정보를 정의하기 때문이다. 사용자가 양식을 작성하고 나면, 사용자의 특정 사본이 클래스의 인스턴스가 된다. 여기에는 사용자에 관련된 실제 정보가 포함되어 있다.

여러 다른 인스턴스를 생성하기 위해서 양식의 여러 사본을 작성할 수 있지만, 양식을 가이드로 작성하지 않으면 어떤 정보가 필요한지 모르기 때문에 길을 잃을 수 있다. 그러므로, 객체의 개별 인스턴스를 생성하려면, 클래스를 정의해서 무엇이 필요한지 먼저 명시해주어야 한다.


클래스를 정의하는 방법

모든 클래스 정의는 class 키워드로부터 시작한다. 괄호 안에 어떤 매개변수도 필요하지 않다는 점을 제외하고는 함수의 시그니처와 비슷하다. 또한, 클래스 정의 이하 들여쓰기 된 모든 코드는 클래스의 본문으로 여겨진다. 다음 예제의 Dog 클래스를 참고해보자.

class Dog:
	pass

Dog 클래스의 본문은 pass 키워드 단일문으로 구성되어 있다. pass는 최종적으로 코드가 사용될 자리 표시자로 주로 사용된다. pass 키워드를 사용함으로써 오류 없이 코드를 실행할 수 있다.

함수나 변수 이름과는 달리, 파이썬에서 클래스의 이름을 정의하는 컨벤션으로 카멜케이스(CamelCase) 표기법을 사용한다.
예를 들어, 개 품종인 Jack Russell Terrier로 클래스 이름을 지으면 JackRussellTerrier가 된다.

Dog 클래스에 많은 속성들을 추가할 수 있지만 간단히 이름(name)과 나이(age)를 추가해보도록 하자.  모든 Dog 객체가 가져야하는 클래스 속성, 혹은 인스턴스 속성을 정의하려면 __init__()이라고 불리는 특별한 메서드를 정의해야 한다. 이 메서드는 새로운 Dog 객체가 생성될 때 마다 작동하고 파이썬에게 초기 상태를 알려준다.

즉, 객체 속성의 초기 값은

항상 __init__()의 첫 위치 인수는 클래스 인스턴스를 참조하는 변수이다. 이 변수의 이름은 보편적으로 self이다. 인수 self 후, 클래스의 인스턴스를 생성하기 위해 필요한 모든 인수를 명시해줄 수 있다.

Dog 클래스의 정의를 업데이트 한 다음 예제는, 두 인스턴스 속성인 nameage를 생성하기 위해 어떻게 __init__() 메서드를 작성해야 하는지 보여준다.

class Dog:
	def __init__(self, name, age):
		self.name = name
		self.age = age
클래스에 속한 함수(function)는 인스턴스 메서드(instance method)라고 불린다. 왜냐하면 클래스의 인스턴스에 속하기 때문이다.
예를 들어, list.append()string.find()도 인스턴스 메서드이다.

__init__() 메서드의 본문에는 변수 self를 사용한 두개의 문(statement)가 있다. 첫 번째 줄 self.name = name에서는 name이라는 인스턴스 속성이 생성하고, __init__() 메서드에 전달된 변수 name값을 할당한다. 두 번째 줄에서는 age라고 불리는 인스턴스 속성이 생성되고 age 인수의 값이 할당된다.

인스턴스 속성은 각 객체에 대해 특정하지만, 클래스 속성은 모든 인스턴스에 대해 동일하다. 다음 예제에서는, species라고 불리는 클래스 속성이 생성되고 값 "Canis familiaris"가 할당된다.

class Dog:
	# 클래스 속성
	species = "Canis familiaris"

	def __init__(self, name, age):
		self.name = name
		self.age = age

클래스 속성은 클래스의 첫 번째줄 아래 및 메서드 정의 외부에 정의된다. 클래스 속성에는 반드시 값이 할당되어야 한다. 왜냐하면 초기 값이 무엇인지 결정하기 위한 인수 없이 클래스 인스턴스에서 인수 없이 생성되기 때문이다.

속성이 클래스의 모든 인스턴스에 대해 동일한 초기 값을 가져야 할 때 마다 클래스 속성을 사용해야 한다. 인스턴스가 생성되기 전에 명시되어야만 하는 속성에 인스턴스 속성을 사용할 수 있다.

Reference