Skip to main content

Command Palette

Search for a command to run...

print(obj.__secret) # 오류 발생! (직접 접근 불가)

Published
•4 min read•View as Markdown
U
Keep learning toward wellbeing life with co-livers

객체 지향 프로그래밍

클래스와 인스턴스

  • 클래스 메서드들은 중첩된 def이며, 특수한 첫번째 인자는 묵시적으로 대상 인스턴스를 받는다.

네, 정확합니다! self를 설명하는 내용이 맞습니다.

이 문장을 조금 더 자세히 풀어드리면 다음과 같습니다.

1. "클래스 메서드들은 중첩된 def이며"

파이썬에서 클래스 내부의 함수(메서드)는 클래스라는 '객체 내부'에 정의되어 있습니다.

  • def는 함수를 만드는 키워드인데, 클래스라는 범위(scope) 안에 정의되어 있기 때문에 일반 함수와는 약간 다른 방식으로 동작할 준비를 합니다.

2. "특수한 첫번째 인자는 묵시적으로 대상 인스턴스를 받는다"

이 부분이 바로 self에 대한 핵심 설명입니다.

  • 묵시적으로(Implicitly) 받는다는 것: 우리가 메서드를 호출할 때 obj.method()라고 쓰면, 파이썬 인터프리터가 자동으로 그 객체 자신(obj)을 메서드의 첫 번째 인자로 전달해줍니다. 그래서 우리가 직접 method(obj)라고 쓸 필요가 없는 것이죠.
  • 특수한 첫 번째 인자: 관례적으로 이 첫 번째 인자 이름을 self라고 짓습니다. (물론 this나 a라고 써도 문법적으로는 에러가 안 나지만, 전 세계 파이썬 개발자들 사이의 절대적인 약속입니다.)

이해를 돕기 위한 코드 예시

class MyClass:
    def hello(self): # 이 self가 바로 '대상 인스턴스'를 받는 그 특수한 인자입니다.
        print("안녕!")

obj = MyClass()
obj.hello()

위의 obj.hello()를 호출할 때, 내부적으로 파이썬은 사실 이렇게 처리합니다: MyClass.hello(obj)

즉, obj라는 인스턴스가 self라는 매개변수로 쏙 들어가는 것입니다.

왜 이렇게 하나요?

클래스라는 틀(붕어빵 틀)은 하나지만, 거기서 만들어지는 인스턴스(붕어빵)는 여러 개일 수 있습니다. 각 인스턴스는 서로 다른 데이터를 가질 수 있는데, "지금 내 데이터를 처리해야 하는 대상이 누구인지"를 명확하게 알기 위해 그 인스턴스 자신을 메서드에게 전달해 주는 것입니다.

의사 프라이빗(pseudo private) 속성

기본적으로 모듈 및 클래스의 모든 속성 이름은 모든 곳에서 볼 수 있다. 특별한 관례가 일부 데이터 숨김을 허용하지만, 그것은 대부분 이름 충돌을 방지하기 위해 설계된 것이다.

모듈 프라이빗

클라이언트가 from module import *를 사용할 때 모듈 안에서 밑줄한 개인 이름(예: _X) 및 모듈의 __all__ 리스트에 나오지 않는 이름은 복사되지 않는다. 하지만 다른 임포트 문장 형식으로 이름에 여전히 접근할 수 있으므로 엄밀히 말하면 프라이빗이 아니다.

클래스 프라이빗

class 문 내의 어디든 두 개의 밑줄로 시작하는 이름(예: __X)에 한해서 컴파일 시에 그것을 포함하는 클래스 이름을 접두사로 포함하도록 맹글링된다(mangled)(예: _Class__x). 추가로 클래스 이름 접두사는 자신을 포함하는 클래스로 그 이름을 지역화하므로 self 인스턴스 객체 및 클래스 계층 모두에서 구별 가능하게 된다. 이는 같은 이름의 메서드나 상속 체인 하부의 단일 인스턴스 객체 내부 속성들에 의해 일어날 수 있는 의도하지 않은 충돌을 피하는 데 도움을 준다(주어진 attr이 주어지면 프레임워크 내부의 모든 self.attr로의 대입은 단일 인스턴스 이름 공간을 변경한다). 하지만 맹글링된 이름을 통해 그러한 속성들에 여전히 접근할 수 있으므로 엄밀히 말하면 프라이빗이 아니다.

프라이빗과 유사한 접근 제어는 __getattr__() 및 __setattr__() 메서드에서 속성 접근을 확인하는 프록시 클래스로도 구현될 수 있다.

파이썬의 '의사(pseudo) 프라이빗'이라는 표현은 "완벽하게 숨겨진 것은 아니지만, 실수로 건드리는 것을 방지하기 위한 장치를 제공한다"는 의미입니다.


1. 핵심 개념: 이름 맹글링(Name Mangling)

파이썬은 __변수명처럼 밑줄 두 개(__)로 시작하는 속성을 만나면, 컴파일 과정에서 자동으로 이름을 바꿉니다. 이를 '맹글링(Mangling, 뒤섞기)'이라고 합니다.

  • 변환 규칙: __변수명 → _클래스명__변수명

예시:

class MyClass:
    def __init__(self):
        self.__secret = 10  # 내부에서는 __secret으로 보임

obj = MyClass()
print(obj._MyClass__secret) # 10 (실제로는 이렇게 이름이 바뀌어 있음)

2. 왜 이렇게 하나요? (의도)

진짜 보안을 위해서라기보다는 '이름 충돌 방지'가 주 목적입니다. 특히 상속(Inheritance) 상황에서 문제가 발생하기 때문입니다.

충돌 상황 예시:

  1. 내가 만든 클래스 A가 self.count = 0이라는 속성을 씁니다.
  2. 그런데 부모 클래스(또는 나중에 라이브러리가 추가한 클래스)에도 우연히 self.count라는 속성이 있다면?
  3. 두 클래스가 같은 self를 공유하므로, 한쪽이 값을 바꾸면 다른 쪽 값이 의도치 않게 변경되는 '속성 덮어쓰기' 현상이 발생합니다.

맹글링의 해결책: __count라고 쓰면, 클래스 A의 것은 _A__count로, 부모 클래스의 것은 _Parent__count로 이름이 각각 고정됩니다. 그래서 서로의 영역을 침범하지 않게 됩니다.

3. 왜 '의사(Pseudo)' 프라이빗인가요?

엄밀한 의미의 프라이빗(자바나 C++의 private 키워드)은 외부에서 절대로 접근할 수 없습니다. 하지만 파이썬은 "작정하고 접근하면 접근할 수 있다"는 특징 때문에 '의사' 프라이빗이라고 부릅니다.

  • 파이썬의 철학: 파이썬은 "모든 개발자는 성인이다(We are all consenting adults here)"라는 철학을 가집니다. 즉, 프로그래머가 굳이 내부 속성을 확인하고 싶다면 막지 않겠다는 것입니다.
  • obj._MyClass__secret처럼 이름을 바꾸면 외부에서도 얼마든지 데이터를 읽고 쓸 수 있습니다. 따라서 강제적인 차단이 아니라, "이건 내부용 변수니까 건드리지 마세요"라는 경고 표시에 가깝습니다.

요약

  1. __변수명을 쓰면 이름이 _클래스명__변수명으로 자동으로 바뀐다(맹글링).
  2. 이름이 바뀌기 때문에 외부에서 실수로 이름을 부르기가 어렵다.
  3. 상속 관계에서 하위 클래스와 상위 클래스 간의 속성 이름 충돌을 방지한다.
  4. 하지만 진짜 못 보게 숨긴 것은 아니므로(이름만 알면 접근 가능), '완벽한 프라이빗'이 아닌 '의사(Pseudo) 프라이빗'이다.

More from this blog

카메라 영상 $\rarr$ 유속 추정(A to Z) 프로젝트 소개

프로젝트 목적 말 그대로 카메라 영상에서 하천 흐름의 유속값과 유속의 분포 데이터를 안정적으로 추정하기 위한 파이프 라인을 설계하기 위해 제로 베이스에서 시작해서 이해도를 높여보기 위한 프로젝트 수식에 대한 이해와 함께 opencv, python 기반으로 실제 구현 코드를 작성해보고 및 소스코드의 현장 적용성도 함께 검토하고자 한다. 프로젝트 수행 방법 기존에 사용하고 있는 태블릿의 코틀린 코드와 UI를 최대한 그대로 사용하고자 하며, 1...

May 1, 20265 min read2

9장 함수(Python)

9.3 인수와 매개변수 자바와 동일하게? 함수 외부에서는 인수라고 하지만 내부에서는 매개변수라고 한다. 함수로 전달한 값을 인수라고 부른다. 인수의 값은 함수 내에서 해당하는 매개변수에 복사된다. 함수가 명시적으로 return 을 호출하지 않으면, 호출자는 반환값으로 None을 얻는다. 9.3.1 유용한 None None은 아무것도 없다는 것을 뜻하는 파이썬의 특별한 값이다. 빠뜨린 빈 값을 구분하기 위해 None을 사용한다. 불리언 값 ...

Apr 20, 202613 min read

[ITSantiago]의 개발 블로그 | TIL & Tech Log

36 posts