[python] 언더스코어('_')와 더블 언더스코어('__')

gunny·2024년 4월 11일
0

Python

목록 보기
23/29

python : 언더스코어('_'), 더블 언더스코어('__')

Instruction

개발을 하다 보니, 자주 쓰는 모듈의 객체가 정의된 클래스들을 보면
언더스코어('_') 와 더블 언더스코어('__') 가 메소드 명 앞에 쓰이는 것을 볼 수 있다.
이 차이를 좀 제대로 정리하고 싶어서 기록한다.

(1) 언더 스코어 (_, Single Underscore)

  • 언더스코어를 사용한 변수는 프로그래머에게 private처럼 사용하므로 외부에서 접근하지 말라는 의미이다.
    해당 모듈을 외부에서 참조할 경우 변수가 ㅇ벗는 것처럼 보이지만 실제로는 접근이 가능하다.
    예를 들어, underScore.py 파일에 v1, v2, _v3에 각각 아래와 같은 변수를 할당하고,
underScore.py

v1 = "variable1"
v2 = "variable2"
_v3 = "variable3"

test.py 에서 underScore 모듈을 import 한후 dir() 함수를 이용해서, 현재 네임스페이스에 정의된 모든 이름을 나열해본다.

네임스페이스 ? => https://velog.io/@heyggun/python-NameSpace%EB%84%A4%EC%9E%84%EC%8A%A4%ED%8E%98%EC%9D%B4%EC%8A%A4

그래서 dir로 현재 네임스페이스에 정의된 모든 이름을 나열해보면,

test.py

from underScore import *
print(dir())

# output
['__annotations__', '__builtins__', '__cached__', '__doc__', 
'__file__', '__loader__','__name__', '__package__', '__spec__', 
'v1', 'v2']

가 나온다. 언더 스코어('_')를 붙인 변수 _v3는 네임스페이스에서 빠져있다.

그러나, 해당 모듈을 import 하면 해당 변수 _v3를 로드해올 수 있다.

test.py

import underScore
from underScore import *

print(dir())
print(underScore.v1)
print(underScore.v2)
print(underScore._v3)

# output
['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'underScore', 'v1', 'v2']
variable1
variable2
variable3

직접 가져다 쓰는 것은 가능한데 접근 제한을 권유 하지만 강제하지는 않는다. 언더스코어를 붙이는 것은 일종의 컨벤션(convention)이다.

컨벤션(Convention) : 일종의 관례 또는 약속
프로그래밍에서 컨벤션은 코드를 작성하거나 구성할 때 따르는 일련의 규칙이다.

더블 언더스코어(__, Double Underscore)

  • 더블 언더스코어 역시 private를 구현하기 위해서 사용한다.
    DoubleUnderScore.py 파일에서 '' 더블 언더스코어로 `privateVar' 에 'Double Under Score' 문자열을 할당했고,
    '_' 싱글 언더스토어로 `_semiprivateVar'에 'single Under Score'를 할당했다.
DoubleUnderScore.py

class MyClass:
    def __init__(self):
        self.__privateVar = "Double Under Score"
        self._semiprivateVar = "single Under Score"

그리고 test.py 파일에서 해당 클래스를 import 하고
싱글 언더스코어로 정의한 _semiprivateVar 는 접근이 가능하다.

test.py

from DoubleUnderScore import *

myclass = MyClass()
print(myclass._semiprivateVar)

#output
single Under Score

그러나, 더블 언더스코어를 사용하면 접근 자체가 불가하다.

test.py

from DoubleUnderScore import *

myclass = MyClass()
print(dir(myclass))
print(myclass._semiprivateVar)
print(myclass.__privateVar)

#output
['_MyClass__privateVar', '__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__', '_semiprivateVar']
single Under Score
Traceback (most recent call last):
  File "/Users/geonheekim/Desktop/langchain_note/test.py", line 6, in <module>
    print(myclass.__privateVar)
AttributeError: 'MyClass' object has no attribute '__privateVar'. Did you mean: '_semiprivateVar'?

  • 더블 언더스코어 사용은 애초 클래스 내 비슷한 이름들끼리 충돌을 방지하기 위함이다.
    더블 언더스코어를 사용해서 python 인터프리터에게 해당 변수를 다른 이름으로 치환하라고 알려준다.
    이 규칙은 어디서든 동일하게 적용되는데 _변수명_클래스명__변수명으로 치환한다.

즉, MyClass의 __privatVar에 접근하려면 치환된 변수명을 알아야 하는데, 치환된 변수명은 위의 규칙에 따라 _MyClass__privateVar와 같이 변한다.

즉, test.py에서 더블 스코어로 할당한 변수에 접근하려면 다음과 같다.

test.py

from DoubleUnderScore import *

myclass = MyClass()
print(dir(myclass))
print(myclass._MyClass_privateVar)
print(myclass._semiprivateVar)

# output
['_MyClass__privateVar', '__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__', '_semiprivateVar']
Double Under Score
single Under Score
profile
꿈꾸는 것도 개발처럼 깊게

0개의 댓글