본문으로 바로가기

Name Magling

category Language/Python 2022. 12. 5. 21:39
728x90
반응형

Name Magling이란

Name Maggline은 변수나 메서드 앞에 언더바(_) 두 개를 붙여서 다른 이름으로 바꿔 버리는 것을 말한다

이름을 바꾼다고?

속성으로 foo를 가지고 있는 클래스가 존재한다. Namespace를 보게 되면 마지막 foo 그대로 Namespace에 존재하는 걸 확인할 수 있다.

class Sample:
    def __init__(self):
        self.foo = 'a'

[..., 'foo']

이어서 foo 앞에 언더바(_) 두 개를 붙여서 Namespace를 확인해보자

class Sample:
    def __init__(self):
        self.__foo = 'a'

['_Sample__foo', ...]

foo라고 존재하던 속성이 ‘_Sample_foo’라고 변경된 것을 확인할 수 있다. method도 동일하다

...
def __method(self):
    return 1
...

['_Sample__foo', '_Sample__method', ...]

 

그래서 이걸 언제 사용할까?

 

1. 외부에서 접근을 막을 때

위에서 작성 예제 코드 그대로이다.

class Sample:
    def __init__(self):
        self.__foo = 'a'

    def __method(self):
        return 1


if __name__ == '__main__':
    sample = Sample()
    print(sample.__foo)

위 코드의 결과는 다음과 같다.

Traceback (most recent call last):
  File "/Users/jako/private/git-repo/PythonResearch/Research/NameMaggling.py", line 14, in <module>
    print(sample.__foo)
AttributeError: 'Sample' object has no attribute '__foo'

외부에서 Name Maggling이 적용된 속성에 접근하려 하자 AttributeError가 일어난다.

 

2. 클래스 간 오버 라이딩 막기

다음 예제를 살펴보자

class Sample:
    def __init__(self):
        self.__foo = 'a'

class Example(Sample):

    def get_foo(self):
        return self.__foo

if __name__ == '__main__':
    example = Example()
    example.get_foo()

슈퍼 클래스에는 self.__foo 즉 Name Maggline이 적용된 변수가 존재하고 이를 서브 클래스의 메서드가 접근하는 구조이다. 위 코드의 결과는 다음과 같이 AttributeError가 일어나며 접근이 불가한 것을 알 수 있다.

Traceback (most recent call last):
  File "/Users/jako/private/git-repo/PythonResearch/Research/NameMaggling.py", line 14, in <module>
    example.get_foo()
  File "/Users/jako/private/git-repo/PythonResearch/Research/NameMaggling.py", line 9, in get_foo
    return self.__foo
AttributeError: 'Example' object has no attribute '_Example__foo'. Did you mean: '_Sample__foo'?

 

사실 접근할 수 있다. 

그렇다 클래스 외부에서 접근하기 위한 방법은 Namespace에서 노출된 값 그대로 접근하면 접근이 가능하다.

class Sample:
    def __init__(self):
        self.__foo = 'a'


if __name__ == '__main__':
    sample = Sample()    
    print(sample._Sample__foo)

 

728x90
반응형