파이썬에서는 정보 은닉(외부 접근 제한)을 표현하는 방법입니다.
파이썬에서는 접근 지정자의 지원이 타 OOP언어에 비해 느슨합니다.
'_'(underscore)문자를 이용하여 비슷한 개념을 표현합니다.(name mangling)
_ : 외부 접근을 제한한다는 개념 (타 OOP 언어에서 protected개념과 비슷합니다. 강제성은 없습니다.)
__: 해당 형식에서만 접근 가능함 (타 OOP 언어에서 private개념과 비슷합니다. 강제성은 없습니다.)
속성과 메서드 모두 적용 가능합니다.
멤버 접근 제한이나 하위 클래스의 오버라이딩을 제한하는 용도로 사용됩니다.
__ 의 기본적 형태는
class exam:
def __init__(self, name=None, age=0):
self.__name = name
self.__age = age
def printInfo(self):
print(self.__name, self.__age)
이런식으로 변수 self뒤에 __ 를 붙여주며 사용합니다.
제한이 있을때와 _ 일때 __ 일때를 나눠 뭐가 어떻게 다른지 정리해보겠습니다.
먼저 제한이 없을때 입니다.
class exam:
def __init__(self, name=None, age=0):
self.name = name
self.age = age
def printInfo(self):
print(self.name, self.age)
def main():
p1 = exam('홍길동', 20)
print(p1.__dict__)
print(dir(p1))
p1.__dict__['age'] = 30
print(p1.age)
p1.printInfo()
print(p1.age)
print(dir(p1))
main()
dir은 () 안의 객체에 어떤 메서드 어떤 변수를 가지고있는지 모두 표시해주는 파이썬의 내장함수 입니다.
제한이 없을때 사용한다면
{'name': '홍길동', 'age': 20}
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'age','name', 'printInfo']
30
홍길동 30
30
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'age','name', 'printInfo']
이렇게 변화가 없는것을 볼 수 있습니다.
_를 사용했을때의 코드입니다.
class exam:
def __init__(self, name=None, age=0):
self._name = name
self._age = age
def printInfo(self):
print(self._name, self._age)
def main():
p1 = exam('홍길동', 20)
print(p1.__dict__)
print(dir(p1))
p1.__dict__['age'] = 30
p1.__dict__['_age'] = 40
print(p1.age)
p1.printInfo()
print(p1.age)
print(dir(p1))
_을 사용했을때의 결과값입니다.
{'_name': '홍길동', '_age': 20}
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__','_age', '_name', 'printInfo']
30
홍길동 40
30
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_age', '_name', 'age', 'printInfo']
처음 dir을 사용했을땐 위에 제한이 없을때와 같지만 _age가 있지만 _age가 아닌 age에 값을 집어넣게 되면
이렇게 dir에 age가 하나 추가된것을 볼 수 있습니다.
__를 사용했을때의 코드 입니다.
아 우리는 __ 이것을 던더(double underscore)라고 주로 부릅니다.
class exam:
def __init__(self, name=None, age=0):
self.__name = name
self.__age = age
def printInfo(self):
print(self.__name, self.__age)
def main():
p1 = exam('홍길동', 20)
print(p1.__dict__)
print(dir(p1))
p1.__dict__['age'] = 30
p1.__dict__['__age'] = 40
print(p1.age)
p1.printInfo()
print(p1.age)
print(dir(p1))
main()
_를 사용했을때랑 _ 하나의 차이밖에 없지만 결과값은 많이 다릅니다.
결과값입니다.
{'_exam__name': '홍길동', '_exam__age': 20}
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_exam__age', '_exam__name', 'printInfo']
30
홍길동 20
30
['__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__','__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_exam__age', '_exam__name', 'age', 'printInfo']
사용하지도 않은 __exam 이 붙어있는걸 확인할 수 있습니다.
뭐 강제로 p1.__idct__['_exam__age'] = 40 을 하여 값을 변경할 순 있지만 의미가 없는행동입니다.
사용하지 말라고 파이썬에서 이렇게 설정해놓은것이기 때문이죠
여기까지 정보은닉에 대해 정리해보았습니다.
다음은 setter와 getter에 대해 정리해보겠습니다.