객체 지향 프로그래밍 그리고 Python

Research

Featured image

What is Python?

파이썬은 배우기 쉽고, 강력한 프로그래밍 언어입니다. 효율적인 자료 구조들과 객체 지향 프로그래밍에 대해 간단하고도 효과적인 접근법을 제공합니다. 우아한 문법과 동적 타이핑(typing)은, 인터프리터적인 특징들과 더불어, 대부분 플랫폼과 다양한 문제 영역에서 스크립트 작성과 빠른 응용 프로그램 개발에 이상적인 환경을 제공합니다.

그래서 객체가 뭐에요?

Glossary - Python 3.9.4 documentation

python 공식 document에서 거의 모든 용어가 object로 분류되는 만큼 python에서의 모든 것은 obejct, 즉 객체라고 한다. 공식 document에서 정의된 object는 다음과 같다.

Any data with state (attributes or value) and defined behavior (methods). Also the ultimate base class of any new-style class.

즉 어떠한 상태와 행동을 가지고 있는 데이터를 객체라고 합니다.

Class, Instace(object)

image Source:[https://bparanj.gitbooks.io/ruby-basics/content/class-instance-of-class.png]

클래스로 만든 객체를 인스턴스라고도 합니다. 그렇다면 객체와 인스턴스의 차이는 무엇일까? 이렇게 생각해 보자. a = Cookie() 이렇게 만든 a는 객체이다. 그리고 a 객체는 Cookie의 인스턴스이다. 즉 인스턴스라는 말은 특정 객체(a)가 어떤 클래스(Cookie)의 객체인지를 관계 위주로 설명할 때 사용한다. a는 인스턴스보다는 a는 객체라는 표현이 어울리며 a는 Cookie의 객체보다는 a는 Cookie의 인스턴스라는 표현이 훨씬 잘 어울린다

Function, Method

함수는 말 그대로 특정한 기능을 수행하기 위한 명령문으로 볼 수 있습니다. 메소드는 클래스 내에 선언되어 있는 함수를 메소드라고 부릅니다. 즉, 클래스 및 객체와 연관되어 있는 것이라면 메소드고, 그것들과 상관없이 독립적으로 존재하는 것은 함수입니다. 함수가 메소드보다 더 큰 개념이라고 볼 수 있으며, 그래서 메소드를 부를 때 큰 의미로 함수라고 볼 수 있습니다.

OOP(Object-Oriented Programming)

객체 지향 프로그래밍은 컴퓨터 프로그래밍 패러다임중 하나로, 프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법입니다.

Keyword1: 추상화

추상화는 불필요한 정보는 숨기고 중요한 정보만을 표현함으로써 프로그램을 간단히 만드는 것입니다. 객체 지향적 관점에서 클래스를 정의하는 것 역시 공통된 속성이나 기능을 묶어놓은 것으로 추상화라고 정의 내릴 수 있습니다.

Keyword2: 캡슐화

캡슐화는 클래스 혹은 객체 단위를 생성하는데 있어서 필수적인 요소이며 객체에 대해 필요한 속성과 행위를 하나의 단위로 처리하는 것을 말합니다.

이와 함께 캡슐화는 객체의 구현 내용에 대한 일부 데이터를 은닉시킴으로써 외부에서 객체의 상태를 마음대로 변경하지 못하도록 하여 잘못된 객체 생성을 방지하거나 또는 중요한 정보를 보호하는 기능을 수행할 수 있습니다. 은닉의 정도는 접근 지정자를 통해 제어하게 됩니다.

접근지정자는 3가지로 구분되며 아래와 같습니다.

Python에서의 캡슐화

사실 Python은 언어 차원에서 캡슐화를 지원하지 않는다. 다른 객체 지향 언어인 Java에서는 Private이라는 키워드를 변수 이름 앞에 붙이면, 외부로부터의 접근이 불가하여 완벽한 캡슐화를 가능하게 하지만 Python에서는 인스턴스가 갖고 있는 모든 변수와 메소드를 확인할 수 있다.

class mangling:
    def __init__(self):
        self.x = 0    # public
        self._y = 1   # protected
        self.__z = 2  # private

test = mangling()
print(test.x) # -> 0
print(test._y) # -> 1
print(test.__z) # -> AttributeError: 'mangling' object has no attribute '__z'
print(test._mangling__z) # -> 2

위의 예제를 살펴보면 public 과 protected 변수는 외부에서 바로 접근할 수 있지만 private 변수는 __를 앞에 붙임으로써 접근을 방지한다. 이렇게 되면 추가적으로 _클래스 이름을 붙여 mangling 시키게 된다. 하지만 맨 마지막 출력물에서와 같이 mangling 되어진 변수를 클래스의 이름과 같이 출력하게 되면 접근이 가능하여 완벽한 캡슐화가 가능하지 않다.

위와 같은 예제의 한계로 Python에서는 조금은 특별한 방식으로 캡슐화를 지원하는데 변수나 메소드 앞에 _ 또는 __ 가 있다면 외부에서 해당 데이터에 직접적인 접근을 하지 말라는 표시를 한다. 물론 어떠한 특수한 기능이 있는 것은 아니고 암묵적인 약속이므로 프로그래머가 자발적으로 준수해야 한다. 이렇게 캡슐화된 변수나 메소드는 데코레이터를 사용하여 간접적으로 조회할 수 있다.

class Person:
    def __init__(self):
        self.__age = 0

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, value):
        self.__age = value

person = Person()

print(person.age) # -> 0
person.age = 30
print(person.age) # -> 30

위의 예제처럼 메소드 바로 위에 @property를 지정하면 함수명으로 하나의 인스턴스를 만들고 그 내부의 getter 메소드에 등록된다. 갱신이 필요하다면 @함수명.setter로 처리해야 한다. 이러한 데코레이터를 사용하여 pythonic한 코드 작성이 가능하며 디버깅시에도 유용하게 사용된다.

Keyword3: 상속

상속은 새로운 클래스가 기존의 클래스의 자료와 연산을 이용할 수 있게 하는 기능이다. 상속을 받는 새로운 클래스를 부클래스, 파생 클래스, 하위 클래스, 자식 클래스라고 하며 새로운 클래스가 상속하는 기존의 클래스를 기반 클래스, 상위 클래스, 부모 클래스라고 한다. 상속을 통해서 기존의 클래스를 상속받은 하위 클래스를 이용해 프로그램의 요구에 맞추어 클래스를 수정할 수 있고 클래스 간의 종속 관계를 형성함으로써 객체를 조직화할 수 있다

Keyword4: 다형성

다형성이란 어떤 한 요소에 여러 개념을 넣어 놓는 것으로 일반적으로 오버라이딩(같은 이름의 메소드가 여러 클래스에서 다른 기능을 하는 것)이나 오버로딩(같은 이름의 메소드가 인자의 개수나 자료형에 따라서 다른 기능을 하는 것)을 의미한다. 이를 통해 프로그램 안의 객체 간의 관계를 조직적으로 나타낼 수 있다.

이는 오버라이딩을 통해 부모 클래스에서 상속된 자식 클래스에서 기존 부모 클래스의 메소드를 수정할 수 있음을 뜻하며, 오버로딩은 그 자체로 매개변수의 타입, 개수 등에 따라 다형성을 부여하게 된다. 예를들면 메소드의 이름은 같아도 되지만 매개변수가 같으면 안된다. 하지만 Python에서는 오버로딩을 공식적으로 지원하지 않는다.

Reference