Python TIL(14) - Encapsulation

random·2021년 4월 8일
0

Python - TIL

목록 보기
13/19

파이썬 캡슐화 학습

작성된 코드를 남들이 쉽게 건들지 못하게 해보자!

캡슐화(Encapsulation)란 무엇일까?

  • 개념소개: 캡슐화는 객체지향 프로그램에서 가장 중요한 기능 중 하나이다. 이는 특정 데이터와 이 데이터를 이용해 동작하는 메소드를 한 데 묶는 기능을 의미하며, 이를 통해 사용자가 변수와 메소드에 직접적으로 접근하여 실수/고의로 데이터를 변경하는 행위를 미연에 방지해준다.우리가 흔히 사용하는 데이터와 함수를 내포하는 '클래스'가 바로 이 캡슐화의 한 예라고 할 수 있다.

  • 사용이유 예시: 회사를 예로 들어 설명하자면, 한 회사에 판매, 총무, 경영 등 다양한 부서가 있고 각 부서마다 자신이 처리하는 데이터 정보가 다르다. 만일 판매측에서 총무가 보유하고 있는 데이터에 임의로 접근을 하여 이를 마음대로 가져오거나, 수정하려고 하면 회사 전체에 큰 혼란을 야기할 것이다. 이렇게 데이터에 대한 접근과 수정을 위해선 총무측 담당자에게 직접 연락해서 데이터 사용에 대한 관련 중요 정보를 직접듣고 협의하는 시간을 거쳐야만 할 것이다.
    => 캡슐화도 프로그래밍 측면에서, 다른 개발자가 너무 쉽게 데이터에 접근해서 실수 또는 고의로 데이터를 변경하는 불상사를 막기위해, 그리고 코드 작성자의 의도를 추후에 읽어볼 타인을 위해 더 확실하게 하기 위해 경계병을 세워 놓은 것이다.

  • 캡슐화 종류: 파이썬은 자바의 '접근제한자(Private)' 설정 처럼 완벽한 외부 접근을 통제하는 기능이 내재 되어 있지 않는다. 따라서 이에 비록 못미치지만 파이썬에서 나름 방어장치를 설치해 볼 수 있다. 파이썬에서의 캡슐화는 크게 1. Private Variable 개념을 이용 하는 방법과, (어떤 한 객체 변수를 다른 한 객체의 메소드를 이용해야지만 변경할 수 있게 하는 방법), 2. Protected members 개념을 이용하는 방법 (클래스 외부에서 접근이 불가하고 해당 클래스 내부나 하위 클래스에서만 접근이 가능한 방법) 크게 이 두 가지로 나뉜다. 더 자세한 내용은 아래로...


그렇다면, 캡슐화는 어떻게 할까?

1. Private Variables:

  • 어떤 한 객체 변수를 다른 한 객체의 메소드를 이용해야지만 변경할 수 있게 하는 방법이다. 변수명앞에 언더스코어 __ 를 이와 같이 두개 붙여주면 된다. 흔히들 'name mangling' (이름 장식) 기법으로도 통칭된다.

  • Private Variable은 대게 실수에서 비롯된 오류를 방지하고자 설정해놓은 간이 장치이다. 사용자가 정 원한다면 의도적으로 해당 변수에 접근해서 데이터를 변경하는 것이 가능하기 때문에, 아예 접근 불가능한 것이 아니라 접근할 수 있는 변수의 이름이 달라지는 것(mangling)이라고 이해할 수 있다. 참고로, 이 기법은 디버거 사용을 위해 꽤 유용하게 쓸 수 있다.

<Private Variables 코드예제(1): 변수 접근 불가>


class Example():

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

call = Example('Ray')
print(call.__name)
출력결과:
AttributeError: 'Example' object has no attribute '__name'
  • 출력결과의 에러메세지를 보면, Example 클래스에 __name 이라는 속성이 없다는 것을 알 수 있다. 실제로 클래스를 정의할 때 사용한 변수명으로는 접근이 불가능한 것을 알 수 있다.

그렇다면 위 __변수에 대한 접근 및 수정을 어떻게 하면 잘 하는 걸까?

<Private Variables 코드예제(2): Private 변수 접근/수정의 올바른 예>

class Example():
    def __init__(self, name):
        self.__name = name

    def update_name(self, name):      #name 변경 메소드 선언
        self.__name = name            #name 값 변경

    def get_name(self):               #name 값 반환 메소드 선언
        print(self.__name)            #name 값 출력


call = Example('Ray')
call.get_name()

call.update_name('Kim')
call.get_name()
출력결과:
Ray
Kim
  • 위와 같은 Private 변수 (__name)에 대한 접근 및 수정을 용이하게 하기 위해서 사용할 수 있는 좋은 방법은, 해당 클래스 안에 이 변수를 수정하기 위한 별도의 메소드를 선언하여 호출하는 방식을 활용하는 것이다.
  • 위 코드예제(1)번과 달리 Example 클래스에 새롭게 update_name, get_name 메소드를 선언하여서 각각 __name의 값을 변경하고 이에 대한 값을 출력하는 기능을 추가하였다.
  • 위와 같이 추가 메소드 선언시, 메소드명에 본인이 의도한 바를 명확히 밝히고 나면 실제로 해당 메소드가 호출 되었을 때 코더의 의도를 더욱 분명하게 확인할 수 있다. 이는, 혹시 모를 실수로 인해 변경이 되면 안되는 변수를 최대한 보호하는 이점도 제공한다. 단순히 __name 변수명을 직접 활용하는 단순한 접근을 벗어나 (타인을 배려하지 않은 이기적인 모습의 코딩 수정이 아닌) 조금 더 성숙한 코딩 문화를 지향하는 좋은 코딩습관이다.

2. Protected Members:

클래스 외부에서 접근이 불가하고 해당 클래스 내부 하위 클래스에서만 접근하게끔 설정하는 기법이다. 두 개를 붙인 Private Variable과는 달리, 변수명 앞에 언더스코어 _ 를 하나 붙이면 된다.

<Protected Members 코드예제>


# Base Class 생성
class Base:
    def __init__(self):
         
        # Protected member 표현
        self._number1 = 1
 
 
# Derived Class 생성 
class Derived(Base):
    def __init__(self):
         
        # Base Class 생성자 호출
        Base.__init__(self)
       
        print("Calling protected member of base class: ")
        print(self._number1)
 
obj1 = Derived()      
obj2 = Base()
 


print(obj2.number1)
출력결과:
Calling protected member of base class: 
1
AttributeError: 'Base' object has no attribute 'number1'
  • Base(상위) 클래스에서 만든 변수 self._number1를 Derived(하위) 클래스에서 호출하여 작성된 내용을 성공적으로 출력하였다.
  • 클래스 외부에서 객체를(obj2) 만들어 함수 호출을 시도해 보았지만 AttributeError가 나면서 실패하였다. 이는 Protected members는 클래스 외부 호출이 불가하다는 사실을 보여준다.

0개의 댓글