파이썬(python) - 네임 맹글링(name mangling)
네임 맹글링(name mangling)이란?
네임 맹글링은 짓이기다(mangle)라는 어원에서 유추할 수 있듯이 파이썬이 변수/함수의 이름을 짓이겨서 다른 이름으로 바꿔버리는 것을 말합니다. 맹글링을 적용하고 싶은 변수/함수명 앞에 언더바(_)를 두 개 붙여서 적용할 수 있습니다.
맹글링에 대해서 잘 모르시는 분들은 이전 포스팅의 4-3문단을 참조해주세요.
오늘 포스팅에서는 맹글링을 언제 사용하는지에 대해서 간단히 다뤄보겠습니다.
그래서 맹글링은 언제 사용하나요
파이썬에서 맹글링은 크게 2가지 상황에서 사용할 수 있습니다.
첫 번째는 클래스의 속성값을 외부에서 접근하기 힘들게 할 때(private화)
두 번째는 하위 클래스가 상위 클래스의 속성을 오버라이딩 하는 것을 막을때 입니다.
1. 클래스의 속성값을 외부에서 접근하기 힘들게 할 때
class TestClass:
def __init__(self):
self.name = "왕춘삼"
self.age = 30
self.hobby = "인형놀이"
man = TestClass()
print(man.name, man.age, man.hobby)
출력 결과
왕춘삼 47 인형놀이
위와 같은 코드가 있습니다.
보시다시피 아무런 변화를 주지 않은 평범한 코드이고 따라서 클래스의 속성값을 외부에서 손쉽게 접근할 수 있습니다.
만약 여기서 hobby라는 속성을 조금 숨기고 싶다면? 이럴 때 맹글링을 적용하면 됩니다.
(아무래도 30살에 인형놀이가 취미라고 하면 사회적인 시선이 고울 것 같지는 않기 때문에..)
class TestClass:
def __init__(self):
self.name = "왕춘삼"
self.age = 47
self.__hobby = "인형놀이"
man = TestClass()
print(man.name, man.age, man.__hobby) # AttributeError: 'TestClass' object has no attribute '__hobby'
맹글링 적용시 속성의 이름이 변경되기 때문에 외부에서는 더 이상 해당 속성 이름으로 접근할 수 없게 됩니다.
어느 정도 private의 성격을 띄게 된 것입니다.
man = TestClass()
print(dir(man))
['_TestClass__hobby', '__class__', '__delattr__', '__dict__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__',
'__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name']
단, dir함수를 써 보면 알 수 있지만 이는 완벽한 private은 아닙니다.
첫 인덱스에 '_TestClass__hobby'라는 요소가 보이죠?
저 요소가 바로 맹글링이 적용된 hobby속성입니다.
즉 파이썬에서 맹글링을 적용한 속성은 _클래스명__속성명 의 형태로 이름이 바뀌는 것이고 이는 외부의 접근을 조금 어렵게 할 뿐 값을 완벽하게 보호해 주는 것은 아니라는 것입니다.
2. 하위 클래스가 상위 클래스의 속성을 오버라이딩 하는 것을 막을때
클래스가 확장되면서 크기가 커지면 발생할 수 있는 문제인 속성 이름간의 충돌을 막고자 할 때, 특히 오버라이딩을 막고자 할 때 맹글링을 적용시킬 수 있습니다.
class TestClass:
def __init__(self):
self.name = "왕춘삼"
self.age = 30
self.hobby = "인형놀이"
class TestClass2(TestClass):
def __init__(self):
super().__init__()
self.name = "양팔두"
self.age = 23
self.hobby = "벽 보기"
man = TestClass2()
print(man.name, man.age, man.hobby)
출력 결과
양팔두 23 벽 보기
해당 코드는 아무런 조치를 취하지 않았습니다.
따라서 아무런 제약 없이 하위 클래스에서 상위 클래스의 속성들을 오버라이딩 할 수 있습니다.
class TestClass:
def __init__(self):
self.name = "왕춘삼"
self.age = 30
self.__hobby = "인형놀이"
class TestClass2(TestClass):
def __init__(self):
super().__init__()
self.name = "양팔두"
self.age = 23
self.__hobby = "벽 보기"
man = TestClass2()
print(man.name, man.age, man.__hobby)
# AttributeError: 'TestClass2' object has no attribute '__hobby'
하지만 이와 같이 오버라이딩을 막고싶은 속성에 맹글링을 적용시키면 AttributeError가 발생합니다.
이름이 바뀌었기 때문에 __hobby 속성을 애초에 가지고 있지 않은 것으로 취급하는 것 입니다.