포스트

[python] 파이썬은 접근 제어자가 없다? - 맹글링

Python은 접근 제어자가 없다.

애석하게도, 파이썬으로 작성한 코드는 어디서든 접근할 수 있습니다.

숨기는 것과 “이 요소에는 접근하지 마시오” 라고 명시하는 것은 가능하지만, 여전히 접근은 가능합니다.

Java에서 public, private 등의 접근 제어자를 활용해 요소 마다 접근 가능 범위를 수 있는 것과는 대비되죠.

그럼에도, 숨기기 정도와 접근하지 마라고 일러주는 것까지는 가능합니다.

언더 스코어를 통한 접근 제어 표기

Python에서 클래스 내부 요소를 숨기기 위해서 보통 언더 스코어(언더바, _)를 활용합니다.

이를 활용한 네이밍 컨벤션은 클래스 내부 값 뿐만 아닌 함수와 내부 클래스에도 적용이 가능합니다.

변수, 함수, 클래스 모두 1급 객체이므로 취급이 같기 때문이죠.

_ 한 개로 시작하는 요소

클래스 내부와 해당 클래스를 상속받은 클래스의 내부 요소로만 사용하기를 권고

어떠한 강제도 없고, 코드 상 제약도 없는 그저 권고의 의미일 뿐이다.

Java와 비교하자면, protected 접근 제어와 유사한 범위를 의미한다고 볼 수 있다.

__ 두 개로 시작하는 요소 (mangling)

클래스 내부에서만 사용하기를 어느정도 강제

Java의 private 접근 제어자와 동일한 범위를 뜻합니다.

이 경우, 런타임 단계에서 name mangling이 되어 직접 접근을 막아줍니다.

이를 통해 상곡 관계에서 이름의 충돌을 막아주는 역할도 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
class Spam:

    def __init__(self):
        self.x = 1
        self._y = 2
        self.__z = 3

spam = Spam()

spam.x     # 1
spam._y    # 2 / 강제성이 없다.
spam.__z   # AttributeError: type object 'Spam' has no attribute '__z'

이렇듯, _y에는 문제없이 접근 가능하지만, __z는 직접적인 접근 자체가 막힙니다.

다만, IDE를 사용하거나 내부 코드를 뜯어 요소를 확인할 수 있고, 이를 알면 우회적으로 접근할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
class Spam:

    def __init__(self):
        self.x = 1
        self._y = 2
        self.__z = 3

spam = Spam()

spam._Spam__z  # 에러가 발생하지 않는다.

class._class접근할 요소 와 같은 식으로 만들면 외부에서도 접근할 수는 있습니다.

물론, 코드 설계자의 의도에 완전히 반하는 행동인만큼, 쓰지 맙시다!

그럼 __class__ 이건 뭐예용?

매직 메서드입니다.

클래스 내부에서 자동으로 생성되어 일반적으로는 __init____repr__ 말고는 잘 쓸 일이 없습니다.

일반적이지 않은 특수한 동작을 원할 경우 이를 오버라이드하여 만들 수 있습니다.

예를 들어 인스턴스의 대표명을 출력하고 싶은 경우,

클래스 내부에 __repr__ 메서드를 생성(사실상 오버라이드)하여 내 맘대로 바꿀 수 있죠.

1
2
3
4
5
6
7
class Spam:
    
    def __repr__(self):
        return "언제부터 내가 스팸일 거라고 생각했지?"
    
spam = Spam()
print(spam)  # 언제부터 내가 스팸일 거라고 생각했지?

따라서, 앞뒤로 언더스코어 2개가 오는 경우는 접근 제어의 의미는 아닙니다.

물론 둘 다 멋대로 가져다 쓰다가 낭패보기 쉽다는 건 같으니, 잘 알아보고 써야합니다!

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.