__
두개의 언더 스코어를 접두사로 사ㅛㅇ한 변수나 메서드는 name mangling을 겪는다.__variable__
로 정의된 변수는 실제로 클래스 외부에서는 _<클래스 이름> __variable
이라는 이름으로 변경된다.class Myclass:
def __init__(self):
self.__private = 42 # Name Mangling이 적용
def __private(self):
print("This is a private method")
obj = MyClass()
# 외부에서 접근하려고 하면 에러 발생
print(obj.__private) # AttributeError: 'MyClass' object has no attribute '__private'
# name mangling 된 이름으로 접근 가능
print(obj._MyClass__private) # 42
__<name>
으로 정의된 변수는 실제로는 _<클래스 이름>__<name>
으로 변경된다.__<name>
은 외부에서 직접 접근을 제한하기 위한 방법이지만, 여전히 접근할 수는 있다.이름 충돌 방지 : 상속 받은 클래스에서 부모 클래스의 변수나 메서드 이름이 충돌할 때 이를 피하기 위해 사용
변수 보호 : __
로 시작하는 이름은 Python에서 "비공개"로 간주되지만, 실제로 접근은 불가능하지 않기 때문에 단순히 "이름을 바꾸는" 방법으로 보호함.
진정한 은닉을 원한다면 python은 그다지 강력한 보호를 제공하지 않고, 관습에 의존하는 방식임.
__
(두 개의 언더스코어)는 이름 mangling을 통해 외부 접근을 어렵게 만든다. 이 접근 방식은 완벽하게 은닉되는 것은 아니라, 접근을 최소화하고 인터페이스를 통제화하는 방법이 더 중요하다.class MyClass:
def __init__(self):
self.__private = 42
def get_private(self):
return self.__private
이렇게 하면 __private
변수에 대한 직접 접근을 막을 수 있지만 여전히 get_private 메서드를 통해 간접적으로 값을 얻을 수 있다.
class MyClass:
def __init__(self):
self.__private= 42
@property
def private(self):
return self.__private
@private.setter
def private(self, value):
if value > 0:
self.__private = value
else:
raise ValueError("Value must be positive")
이 방식은 객체 외부에서 직접 __private
에 접근할 수 없게 하고, getter와 setter 메서드를 통해 값에 대한 접근을 제어할 수 있다.
_private
와 같은 "약속된" 이름을 사용하여 보호__
(두 개의 언더스코어)는 이름 mangling을 적용하지만, 실제로는 은닉을 제공하지 않기 때문에 _
(하나의 언더스코어)를 사용해 "비공개"로 취급하는 것이 일반적이다. 그러나 이는 완전한 은닉을 보장하지 않고 그저 관례이다.
class MyClass:
def __init__(self):
self._private = 42 # 개발자 관례로 비공개 취급
private
클래스를 다른 곳에서 접근할 수 없게 만들고, 클로저나 내부적으로 사용하도록 제한하는 방식이다.
class OuterClass:
class _InnerClass:
def __init__(self):
self.__private = 42
def __init__(self):
self._inner = self._InnerClass()
def get_private(self):
return self._inner.__private # 외부에서 접근 불가
이 방식은 실용성보다는 특정한 환경에서만 유용할 수 있다.
(일반적인 객체 지향 프로그래밍에서는 잘 사용하지 않기 때문.
유용한 특정환경은 플로그인 시스템에서 모듈화된 구현을 숨기고 싶을때, 내부 API를 보호할때, 클로저(Closer)와 관련된 코드, 성능 최적화를 위한 내부 구현, 상속을 통한 의도적인 제한
[1] 캡슐화(Encapsulation) : 내부 구현 세부 사항을 숨기고, 객체의 상태를 안전하게 유지하며, 외부에서는 정의된 인터페이스만을 통해 상호작용할 수 있도록 하는 설계 원칙. 이를 통해서 객체의 상태를 외부에서 잘못 수정하거나, 예기치 않게 변경되는 것을 방지할 수 있다.
[2] 코드 유지보수 용이성 : 객체 내부의 구현을 은닉하면, 내부 구현이 변경되어도 외부 코드에 영향을 미치지 않게 된다. 이는 시스템의 확장성과 유지보수성을 높인다.
Python은 기본적으로 모든 것이 "공개"라는 철학을 따르지만, Name mangling이나 다른 기법을 통해 의도적으로 은닉할 수 있다. 그러나 Python의 은닉은 철저하지 않기 때문에, 진정한 은닉을 원한다면 인터페이스 제어, 속성(Property) 관리, 클래스 설계 등으로 은닉의 효과를 최대화한다.