파이썬 객체지향 프로그래밍
목차
객체지향 프로그래밍은 어려운 주제입니다. 객체지향 프로그래밍이 세상에 등장한지는 조금 지났지만 다른 학문에 비하면 오랜 역사를 가진 분야는 아닙니다.
한국에서 객체지향이라는 단어를 접하기 시작한 것이 자바의 초창기 정도라고 생각하는데요. 그 때 책방에 객체지향 프로그래밍이라고 써있으면 자바책이었으니까요.
시대가 변하고 아직도 이해하기 어려운 분야라고 생각하고 있습니다만, 어떤 프로그래밍 언어안에서 기술적으로 정의하는 것은 어느 정도 가능하지 않을까 싶습니다.
객체지향의 어려움
사람마다 객체라는 개념이 다르다는 어려움이 있습니다. 순수한 객체(Object)라는 단어는 사람 머리속에만 존재하는 것이다 보니 이것을 구현하기 전까지 결과물에 대한 기대가 다를 수 있다는 점입니다.
누구도 객체(Object)를 본적이 없습니다. 마치 숫자 1처럼 고도의 추상화된 개념을 뽑아서 단어로 사용하고 있습니다.
비지니스 측면에서 예를 들면 어떤 앱을 객체지향 설계에 따라 론칭했는데 잘될줄 알았던 서비스가 실패하는 경우가 있고, 처음 계획과 달리 개발이 순조롭지 못해서 실패하는 경우도 있습니다.
객체지향의 설계에 따라 코드를 재사용하면 뭐든 잘 만들 수 있을 것 같은데 그렇지가 않습니다.
프로그래밍의 생산성을 높이기 위해 객체가 중요하지만 여전히 현실세계는 이름이 붙은 구체적인 인간들이 살아가는 세상입니다.
파이썬에서의 객체 지향
객체에 대한 꼬리에 꼬리를 무는 질문의 함정에 빠지지 않기 위해서는 파이썬 안에서 바라볼 필요가 있습니다.
파이썬에서의 객체 지향이 뭐냐?
바로 코드를 재사용할 수 있는 것 입니다. 코드를 다시 처음부터 작성하지 않고 이미 있는 코드를 찾아서 커스터마이즈 하여 사용하는 것 입니다.
코드를 다시 쓰지 않기 때문에 생상성은 향상됩니다.
심지어 오픈소스를 사용하여 원하는 목적을 달성하는 것도 가능합니다. 기존 파이썬 모듈의 클래스를 상속 후 커스터마이즈하는 것은 일반적인 방식입니다.
클래스 객체와 인스턴스 객체의 차이
파이썬에서 클래스는 실행가능한 객체입니다. 인스턴스도 당연히 프로그램이 생성한 객체입니다.
둘다 자신만의 데이터 영역을 갖습니다.
차이점은 클래스는 하나가 있고 인스턴스는 여러개를 생성할 수 있습니다. 클래스가 하나의 틀이라면 인스턴스는 클래스가 정한 틀 안에서 다른 데이터를 가진 객체입니다.
예를 들어 사람(Person)이라는 클래스를 만들어서 ‘mike’, ‘jane’ 라는 인스턴스를 생성할 수 있습니다.
먼저 Person 을 만들어 보겠습니다.
class Person: def printHello(self): print("Hello!", self) Person.printHello(Person)
Hello! <class '__main__.Person'>
Person 도 실행가능한 코드입니다. toString 에 의해서 main 에 있는 Person 이라는 클래스라고 표시가 됩니다.
아래의 코드에서는 인스턴스를 생성합니다.
class Person: def __init__(self, name, age): self.name = name self.age = age def show(self): print(self.name, self.age) mike = Person("Mike", 15) jane = Person("Jane", 23) mike.show() jane.show()
Mike 15 Jane 23
show 메소드를 사용할 때 인스턴스에 따라 다른 데이터를 가지고 있습니다.
다음 코드를 보면 클래스와 인스턴스의 확실한 차이를 알 수 있습니다.
class Person: def __init__(self, name, age): self.name = name self.age = age def printHello(self): print("Hello!", self) mike = Person("Mike", 15) jane = Person("Jane", 23) Person.printHello(Person) Person.printHello(mike) Person.printHello(jane)
Hello! <class '__main__.Person'> Hello! <__main__.Person object at 0x01B6F4F0> Hello! <__main__.Person object at 0x0385D2F8>
mike 와 jane 인스턴스는 Person 의 객체(object) 이며 위치를 표시합니다. 0x는 파이썬이 관리하는 일종의 메모리 주소와 같습니다. 보면 주소가 다르며 이는 각각 독립적인 메모리 영역에 위치한다는 뜻입니다.
인스턴스는 프로그램이 끝날 때 까지 값을 유지하거나 그전에 더 이상 쓸모가 없어지면 쓰레기수거반(Garbage Collection) 프로그램이 메모리를 해제합니다.
클래스는 하나이고 인스턴스는 여러개 생성할 수 있습니다.
클래스 상속의 의미
마크 러츠의 러닝 파이썬 5판에 따르면 객체지향 프로그래밍은 self 라고 명명된 인수와 상속이라고 불리는 연결된 객체 트리에서의 속성 탐색에 대한 것이 그 내용의 대부분입니다.
좀 기술적이긴 하지만 구체적인 흐름을 알 수 있어서 좋아하는 설명입니다.
파이썬은 다중 상속을 지원합니다.
아래 코드는 파이썬의 클래스 상속이 객체트리의 검색에 대한 내용임을 보여주는 예제입니다.
class C1: x = 1 y = 2 class C2: z = 3 w = 4 class C3(C1, C2): z = 5 I1 = C3() I2 = C3() I1.name = "Instance-1" I2.name = "Instance-2" print(I1.name, I1.w) print(I2.name, I2.z) print(C3.y)
Instance-1 4 Instance-2 5 2
여기서 I1, I2 는 인스턴스이고 나머지는 클래스입니다. 하지만 이들은 모두 객체이기 때문에 검색 트리상에서 연결되있습니다.
I1.name 은 I1의 영역에 있습니다. I1.w 은 w 속성을 찾아서 트리의 위로 올라갑니다. 트리로 올라갈 때는 아래에서 위로 왼쪽에서 오른쪽으로 이동하며 첫번째로 찾은 객체에서 값을 반환합니다.
w는 C2 객체에서 발견합니다. I2도 마찬가지로 트리를 검색합니다. C3에서 z를 찾았으니 C2 까지 올라가지 않습니다. 이것은 속성의 오버라이딩입니다. 아래쪽이 우선하는 것 이지요.
탐색 트리가 아래쪽을 우선하도록 되어 있습니다. 그러므로 속성 뿐 아니라 메소드도 마찬가지입니다.
C3객체는 y를 찾습니다. y는 상위 왼쪽인 C1에서 찾을 수 있습니다.
상속을 말하면 항상 자식이 부모에게 속성과 메소드를 상속을 받고와 같은 추상적인 말로 설명을 했는데 트리 검색과정은 훨씬 기술적으로 깔끔한 설명이 되서 좋습니다.
객체에 따라 동작(메소드)을 다르게 적용하는 다형성에 대하여도 트리 검색 방식으로 설명이 됩니다.
요약
파이썬 객체지향 프로그래밍에서 몇권의 책이나 대학강의를 몇개 수강함으로써 완전히 이해하는 것은 힘들 것입니다.
빠른 시간내에 테크닉을 연마하는 것은 가능하지만 객체지향 프로그래밍의 철학을 실천하며 설계를 개선하는 일은 평생이 걸릴지 모르는 일입니다.
하지만 파이썬과 기술 이슈에 한정한 내용을 파악하는 것은 가능하며 너무 과도한 생각에 빠질 필요는 없습니다. 자바와 달리 파이썬은 클래스를 사용하지 않고 코드를 작성하는 경우도 많습니다.
무리하지 않고 본인의 기술 수준에 따라 필요한 범위에서 학습하면 좋을 것 같습니다.
외부참조문서
Object-Oriented Programming (OOP) in Python 3 – Real Python (파이썬 객체지향 프로그래밍)