[Python] 정보은닉과 dict

2 분 소요

속성 감추기

객체 외부에서 객체 내에 있는 변수, 속성에 직접 접근하지 못하도록 만들 수 있다.

 class Person:
    def __init__(self, n, a):
        self.__name = n       # 이름 정보
        self.__age = a       # 나이 정보

    def add_age(self, a):
        if(a < 0):
            print('나이 정보 오류')
        else:
            self.__age += a

    def __str__(self):
        return '{0}: {1}'.format(self.__name, self.__age)


def main():
    p = Person('James', 22)       # 22살의 James
    # p.__age += 1     # 이 문장을 실행하면 오류가 발생함
    p.add_age(1)
    print(p)

main()

변수를 언더바 두개를 속성이름 앞에 적어주면 외부에서 접근이 불가능하다.

class Person:
    def __init__(self, n, a):
        self._name = n       # 이름 정보
        self._age = a       # 나이 정보

    def add_age(self, a):
        if(a < 0):
            print('나이 정보 오류')
        else:
            self._age += a

    def __str__(self):
        return '{0}: {1}'.format(self._name, self._age)


def main():
    p = Person('James', 22)       # 22살의 James
    # p._age += 1     # 이렇게 안쓰기로 약속했다.
    p.add_age(1)
    print(p)

main()

객체 내 변수 이름 앞에 언더바를 하나만 붙이면 이 변수에 직접 접근하지 없다고 약속하는 것이다. 위 코드와 같이 언더바를 하나 추가해서 변수의 이름을 결정하는 방법이 조금 더 보편적으로 사용된다.



__dict__

객체 내에 해당 객체의 변수 정보를 담고 있는 딕셔너리가 존재한다.

 class Person:
    def __init__(self, n, a):
        self._name = n       # 이름 정보
        self._age = a       # 나이 정보

def main():
    p = Person('James', 22)       # 22살의 James
    print(p.__dict__)

main()
{'_name':'James', '_age':22}

객체 내에 __dict__가 있으며 이는 딕셔너리이다. 여기에는 해당 객체의 변수 정보가 담긴다.

class Person:
    def __init__(self, n, a):
        self._name = n       # 이름 정보
        self._age = a       # 나이 정보

def main():
    p = Person('James', 22)       # 22살의 James
    print(p.__dict__)
    p.len = 178
    p.adr = 'Korea'
    print(p.__dict__)

main()
{'_name':'James', '_age':22}
{'_name':'James', '_age':22, 'len':178, 'adr':'Korea'}

위 코드와 같이 객체에 변수가 추가되면 또는 변수의 값이 변경되면 __dict__에도 그 정보가 반영된다.

class Simple:
    def __init__(self, n, s):
        self._n = n       # 단순 정수
        self._s = s       # 단순 문자열

    def __str__(self):
        return '{0}: {1}'.format(self._n, self._s)


def main():
    sp = Simple(10, 'my')
    print(sp)

    sp.__dict__['_n'] += 10
    sp.__dict__['_s'] = 'your'
    print(sp)

main()
10: my
20: your

__dict__의 정보를 수정함으로써 객체 내 변수의 값을 수정할 수도 있다. 이것을 통해 객체 내에 있는 변수의 값은 __dict__을 통해 관리할 수 있다는 것을 알 수 있다.

class Person:
    def __init__(self, n, a):
        self.__name = n       # 이름 정보
        self.__age = a       # 나이 정보

def main():
    p = Person('James', 22)       # 22살의 James
    print(p.__dict__)

main()
{'_Person_name': 'James', '_Person_age':22}

위 코드를 통해 __dict__에 등록된 속성의 이름이 다음과 같은 패턴으로 수정됨을 알 수 있다.

패턴 : __AttrName –> _ClassName__AttrName

즉 변수 이름에 언더바를 두 개 붙이면 파이썬은 위의 패턴대로 이름을 바꾼다. 물론 객체 내에서는 바뀌기 이전의 이름으로 접근이 가능하다. 그래서 객체 외부에서 접근이 불가능했던 것이다. 따라서 변수 이름에 언더바를 두개 붙이더라도 바뀐이름으로 접근한다면 그 접근까지 막지 못한다.