Python Name Mangling(Feat. private function..?)

realBro·2024년 10월 25일

왜 안될까...

# test.py
def __function1():
    return 1
    
# main1.py
import test
print(test.__function1())

# main2.py
import test

class TestClass():
    def __init__(self):
        print(test.__function1())

TestClass()

main1은 되고 main2는 안된다 왜일까?!!!

Traceback (most recent call last):
  File "/main2.py", line 9, in <module>
    TestClass()
  File "/main2.py", line 7, in __init__
    print(test.__function1())
AttributeError: module 'test' has no attribute '_TestClass__function1'

에러 코드를 보면 _TestClass__fucntion1에 접근하려고 하는 것을 알 수 있다.

파이썬은 Class의 Private Method와 Private Variable에 대해서 Name Mangling을 진행해 변수에 대한 접근을 간접적으로 막는다
보통 public, _protected, __private는 class 내 외부 혹은 부모 자식 class간 접근이 가능하냐에 대해 정의한다.
하지만 Python에서는 _protected는 명시적 의미만을 가지고 실제로 접근이 불가능하게 하지는 않는다. __private 는 앞서 말 했듯이 Name Manling을 통해서 접근이 불가능한 것 처럼 만들어 준다. 함수명의 이름을 Mangling하여 저장하는 것이기 때문에 Mangling 된 이름을 통해서 접근하면 접근이 가능해 진다.

Name Mangling의 동작 방식

  1. Private name of that class의 정의
    • 두 개 이상의 underscore 로 시작하고 두 개 이상의 underscore로 끝나지 않는 식별자(Identifier)
  2. Class 내부에서 이러한 Private Name을 사용하면 외부에서 접근을 어렵게 함
    • Class가 bytecode로 변환 될 때 해당 Name Mangling이 수행된다.(더 긴 이름으로)
      ex) Foo Class안 __sapm 이라는 변수 -> Foo_Foo__spam

그래서 쟤는 왜 저러냐?!

main2에서 test.__function1()는 다른 파일에서 정의된 그냥 함수 이지만, class 내부에서 사용 하려고 했으니 bytecode로 변환 과정에서 Name Mangling이 진행된다. Name Mangling에 의해서 __function1_TestClass__function1으로 변환 하는데 실제 test.py에서는 Name Mangling이 실행 되지 않으니 AttributeError가 발생 하는 것이다. main1에서는 Name Mangling 없이 실행 되기 때문에 에러 없이 진행된다.

해결 방법

해결 방법인지 꼼수인지 더 좋은 방법이 있으면 좋겠다

# test.py
def __function1():
    return 1

# test_wrapper.py
import test

def function1_wrapper():
    return test.__function1()

# main.py
import test_wrapper

class TestClass():
    def __init__(self):
        print(test_wrapper.function1_wrapper())

TestClass()

이렇게 사용하면 모듈에서 private 형태로 정의된 함수를 class 내에서 사용 할 수 있다.

참고

1개의 댓글

comment-user-thumbnail
2024년 10월 25일

너무 유익한 내용 감사합니다 🙏🙏🙏

답글 달기