본문 바로가기

프로그래머/Python

[윤성우의 열혈 파이썬 중급편] 28. 정보 은닉과 __dict __

출처 : 윤성우의 열혈 파이썬 : 중급

28. 정보 은닉과 __dict __

속성 감추기

#person.py

class Person:
    def __init__(self, n, a):
        self.name = n
        self.age = a
    def __str__(self):
        return '{0}: {1}'.format(self.name, self.age)

def main():
    p = Person('James', 22)
    print(p)
    p.age -= 1  # 프로그래머의 실수
    print(p)

main()
  • 오류가 발생한 근본적 원인은 객체 외부에서 객체 내에 있는 변수(속성)에 직접 접근하도록 내버려 두었기 때문이다

메소드 사용

#person2.py

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)
    p.add_age(2)
    print(p)

main()
  • 여전히 변수에 접근할 수 있다
#person3.py
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)
    p.__age += 1    # 오류 발생
    p.add_age(1)
    print(p)

main()
  • 변수 이름 앞에 언더바를 두 개 이어서 붙여주변 외부에서 접근하는 것이 불가
  • 객체 내 변수(속성) 이름 앞에 언더바를 하나만 붙이면 이 변수에 직접 접근하지 않겠다는 약속
    • 더욱 보편적으로 사용된다
#person4.py
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)
    p._age += 1    # 오류 발생은 하지 않으나, 이렇게 안쓰기로 약속했다
    p.add_age(1)
    print(p)

main()

__dict __

# person_dict2.py
class Person:
    def __init__(self, n, a):
        self._name = n
        self._age = a

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

main()
  • 객체 내에는 __dict __이 있으며 이는 딕셔너리이다
  • __dict __에는 해당 객체의 변수 정보가 담긴다
# prt_dict.py
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 \n 20: your
  • __dict __의 정보를 수정함으로써 객체 내 변수의 값을 수정 가능하다
  • 객체 내에 있는 변수의 값은 사실 __dict __를 통해서 관리 된다
  • sp.n += 10과 sp.__dict _['_n'] += 10은 동일하다
# person_dict3.py
class Person:
    def __init__(self, n, a):
        self.__name = n
        self.__age = a

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

main()  # {'_Person_name':'James', '_Person__age':22}
  • __AttrName => _ClassName __AttrName으로 수정되었다
  • 즉 변수 이름에 언더바 2개를 붙이면 파이썬은 위의 패턴대로 이름을 바꾸어 버린다
    • 그래서 객체 외부에서 접근이 불가했던 것
  • 하지만 바뀐 이름으로 접근한다면 그 접근까지 막진 못한다