파이썬에서 '_' 의 의미는 특별하다. 단순히 스네이크 명명법에 쓰일 뿐 아니라 다양한 특정 의미를 가진다. 다음 다섯개의 의미를 갖는다

  1. 인터프리터에서의 사용
  2. 값을 무시하는 경우
  3. 반복문에서의 사용
  4. 숫자값의 구분
  5. 네이밍에서의 사용

1. 인터프리터에서의 사용
python에서는 가장 마지막 표현식의 결과 값을 "_"에 저장한다. 물론 이곳에 저장된 값을 다른 변수에다 저장할 수 있다. "_"를 마치 변수로 사용할 수 있다.

>>> 111-11
100
>>> _
100
>>> a = _
>>> a
100

2. 값을 무시하는 경우
"_"은 값을 무시하는 경우에도 사용할 수 있다. 해당 값을 unpack(변수에서 값을 꺼내는 것)을 무시하고 싶은 경우 해당 값을 _에 저장하면 된다. 마치 temporary, tmp

>>>a, _, b = (1, 2, 3) 
>>> print(a, b)
1 3
>>> a, *_, b = (7, 6, 5, 4, 3, 2, 1)
>>> print(a, b)
7 1
>>> _
[6, 5, 4, 3, 2]

3. 반복문에서의 사용
_를 이용해 루프를 돌 수 있다.  _를 일반 변수처럼도 이용 가능 하다. 

>>> for _ in range(3):
...     print(_)
... 
0
1
2
>>> names = ["Messi", "Son", "Ronaldo", "Neymar"]
>>> for _ in names:
...     print(_,end=' ')
... 
Messi Son Ronaldo Neymar
>>> _ = 1
>>> while _ < 5:
...     print(_, end=' ')
...     _ += 1
1 2 3 4

4. 숫자값의 구분
숫자값이 길때, _를 이용해 구분을 할 수 있다. (일상생활에서의 ','처럼 이용)
이진수, 8진수, 16진수 표현 시에도 사용 가능 하다.

>>> mill = 1_000_000
>>> bin = 0b_1001_1101
>>> hexa = 0x_9D
>>> mill
1000000
>>> bin
157
>>> hexa
157


5. 네이밍에서의 사용
다음 네가지 경우가 있다.

  • 앞에 "_" 1개 : _var
  • 뒤에 "_" 1개 : var_
  • 앞에 "_" 2개 : __var
  • 앞, 뒤에 "_" 2개씩 : __var__

5.1. 앞에 "_" 1개 : _var

 앞에 붙이는 "_"는 내부사용용(internal use)를 명시한다. 

>>> class Goat:
...     def __init__(self):
...         self.name = "Messi"
...         self._num = 10
... 
>>> obj = Goat()
>>> obj.name
'Messi'
>>> obj._num
10


변수명 앞에 "_"을 붙였다고 해당 변수에 접근을 못하는 것은 아니다. 대신 모듈을 import해서 사용하는 효과를 볼 수 있다. 아래와 같이 모듈을 하나 정의해 보자.

##file name is "hello.py"

def func():
	return "hello human"
def _private_func():
	return "I'm not a human"

아래와 같은 경우에 파이썬은 "_"로 시작하는 이름은 import하지 않는다. 그러므로 "_private_func()" 라는 함수를 찾지 못한다.

>>> from hello import *
>>> func()
'hello human'
>>> _private_func()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '_private_func' is not defined

이와 같은 에러를 방지 하기 위해 모듈 자체를 import 할 수 있다. 모듈내에서만 사용 가능 하므로 import한 모듈을 이용해 사용 시킨다.

>>> import hello
>>> hello._private_func()
"I'm not a human"

5.2. 뒤에 "_" 1개 : var_
Python 키워드와 같은 이름의 변수, 함수, 클래스 등을 선언 할 때 사용한다. 뒤에 "_"을 추가함으로써 기존의 키워드들과의 충돌을 막는다.

>>> def func(class): 
  File "<stdin>", line 1
    def func(class): 
             ^^^^^
SyntaxError: invalid syntax

>>> def func(class_): 
...     return class_
... 
>>> func('hello')
'hello'

5.3. 앞에 "_" 2개 : __var
앞에 2개의 "_","__"로 시작하는 명명법은 name mangling이라고 한다. mangle은 뭉개다, 짓이기다라는 뜻인데, 알아보기 힘든모양으로 바꾸는 역할을 한다고 이해하면 되겠다. name mangling은 파이썬 인터프리터로 하여금 해당 서브클래스의 attribute이름을 바꾸어 충돌이 나지 않게 하라고 요청하는 것이다. 즉, 상속과 관계가 있다. 아래 예시를 보자.

>>> class sample():
...     def __init__(self):
...             self.a = 10
...             self._b = 11
...             self.__c = 12
... 
>>> obj = sample()
>>> dir(obj)
['__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__', 
'_b', '_sample__c', 'a']

"dir()" 함수는 클래스 객체의 모든 attribute를 반환한다. "a"와 내부사용용 "_b"은 잘 반환된 것을 볼 수 있다. 반면 "__c"은 보이지 않는다. 대신 "_sample__c"라는 값이 보인다. "__c"를 name mangling한 것이 "_sample__c"이다. 어떤 클래스 A가 "sample()"클래스를 상속 할 때, "A"가 "__c"를 override하는 것을 방지한다. (getter와 setter로 접근할 수 있다.)


5.4. 앞, 뒤에 "_" 2개씩 : __var__
파이썬에서 앞뒤로 2개의 언더바를 적는 방식은 흔히 볼 수 있다. 이는 매직 메소드(magic method)라고 불린다. 이 명명법으로 변수를 할당할 때, 변수명 충돌이 일어날 수 있기 때문에 사용하지 않는 것을 권장한다. 
매직 메소드는 "__init__, __add__, __len__, __repr__"등이 있다. "
__init__"메소드는 생성자라고 보면된다. 호출없이 초기화하는 경우, 자동을 호출되는 함수이며, 클래스의 인스턴스가 생성될 때, 실행된다.

>>> class sample():
...     def __init__(self):
...             self.a = 10
...             print("hello human")
... 
>>> obj = sample()
hello human
>>> obj.a
10


+ Recent posts