36.3 비공개 속성 사용하기

앞에서 만든 Person 클래스에는 hello, name, age, address 속성이 있었습니다.

class Person:
    def __init__(self, name, age, address):
        self.hello = '안녕하세요.'
        self.name = name
        self.age = age
        self.address = address

이 속성들은 메서드에서 self로 접근할 수 있고, 인스턴스.속성 형식으로 클래스 바깥에서도 접근할 수 있습니다.

>>> maria = Person('마리아', 20, '서울시 서초구 반포동')
>>> maria.name
'마리아'

이번에는 클래스 바깥에서는 접근할 수 없고 클래스 안에서만 사용할 수 있는 비공개(private) 속성을 사용해보겠습니다. 비공개 속성은 __속성과 같이 이름이 __(밑줄 두 개)로 시작해야 합니다. 단, __속성__처럼 밑줄 두 개가 양 옆에 왔을 때는 비공개 속성이 아니므로 주의해야 합니다.

class 클래스이름:
    def __init__(self, 매개변수)
        self.__속성 = 

그럼 Person 클래스에 지갑 속성 __wallet을 넣어보겠습니다. 다음 내용을 IDLE의 소스 코드 편집 창에 입력한 뒤 실행해보세요.

class_private_attribute_error.py

class Person:
    def __init__(self, name, age, address, wallet):
        self.name = name
        self.age = age
        self.address = address
        self.__wallet = wallet    # 변수 앞에 __를 붙여서 비공개 속성으로 만듦
 
maria = Person('마리아', 20, '서울시 서초구 반포동', 10000)
maria.__wallet -= 10000    # 클래스 바깥에서 비공개 속성에 접근하면 에러가 발생함

실행 결과

Traceback (most recent call last):
  File "C:₩project₩class_private_attribute_error.py", line 9, in <module>
    maria.__wallet -= 10000    # 클래스 바깥에서 비공개 속성에 접근하면 에러가 발생함
AttributeError: 'Person' object has no attribute '__wallet'

실행을 해보면 에러가 발생합니다. self.__wallet처럼 앞에 밑줄 두 개를 붙여서 비공개 속성으로 만들었으므로 클래스 바깥에서 maria.__wallet으로는 접근할 수 없습니다. 사람이 가지고 있는 지갑은 본인만 사용할 수 있는데 maria.__wallet -= 10000처럼 바깥에서 마음대로 돈을 뺄 수는 없겠죠?

비공개 속성은 클래스 안의 메서드에서만 접근할 수 있습니다. 다음과 같이 돈을 내는 pay 메서드를 만들어봅니다.

class_private_attribute.py

class Person:
    def __init__(self, name, age, address, wallet):
        self.name = name
        self.age = age
        self.address = address
        self.__wallet = wallet    # 변수 앞에 __를 붙여서 비공개 속성으로 만듦
 
    def pay(self, amount):
        self.__wallet -= amount   # 비공개 속성은 클래스 안의 메서드에서만 접근할 수 있음
        print('이제 {0}원 남았네요.'.format(self.__wallet))
 
maria = Person('마리아', 20, '서울시 서초구 반포동', 10000)
maria.pay(3000)

실행 결과

이제 7000원 남았네요.

pay는 돈을 내면 해당 금액을 지갑에서 빼도록 만들었습니다. 이제 지갑에 있는 돈을 쓸 수 있게 되었습니다.

물론 지갑에 든 돈은 굳이 밝힐 필요가 없으므로 print로 출력하지 않아도 됩니다. 보통은 다음과 같이 지갑에 든 돈이 얼마인지 확인하고 돈이 모자라면 쓰지 못하는 식으로 만듭니다.

    def pay(self, amount):
        if amount > self.__wallet:    # 사용하려고 하는 금액보다 지갑에 든 돈이 적을 때
            print('돈이 모자라네...')
            return
        self.__wallet -= amount

이처럼 비공개 속성은 클래스 바깥에 드러내고 싶지 않은 값에 사용합니다. 즉, 중요한 값인데 바깥에서 함부로 바꾸면 안될 때 비공개 속성을 주로 사용합니다. 비공개 속성을 바꾸는 경우는 클래스의 메서드로 한정합니다.

지금까지 클래스 사용 방법에 대해 알아보았습니다. 클래스는 특정 개념을 표현(정의)만 할 뿐 사용을 하려면 인스턴스로 만들어야 한다는 점이 중요합니다. 그리고 속성, 메서드를 사용할 때는 self와 인스턴스를 통해 사용해야 한다는 점도 기억해두세요.

참고 | 공개 속성과 비공개 속성

클래스 바깥에서 접근할 수 있는 속성을 공개(public) 속성이라 부르고, 클래스 안에서만 접근할 수 있는 속성을 비공개(private) 속성이라 부릅니다. 또는, 퍼블릭 멤버, 프라이빗 멤버라고 부르기도 합니다.

참고 | 비공개 메서드 사용하기

속성뿐만 아니라 메서드도 이름이 __(밑줄 두 개)로 시작하면 클래스 안에서만 호출할 수 있는 비공개 메서드가 됩니다.

class Person:
    def __greeting(self):
        print('Hello')
 
    def hello(self):
        self.__greeting()    # 클래스 안에서는 비공개 메서드를 호출할 수 있음
 
james = Person()
james.__greeting()    # 에러: 클래스 바깥에서는 비공개 메서드를 호출할 수 없음