본문 바로가기
Python/기본문법

_ underscore (파이썬)

by yororing 2024. 6. 28.

00 개요

  • 파이썬 파일들을 보면 _ 들이 많이 등장하는데, 그 의미 및 여러가지 역할들에 대하여 정리하고자 함
  • 크게 5가지 용도로 나뉨:
_ 의 용도

1. Interpreter에서 사용
2. 무시하는 값
3. Loop에서 사용
4. 숫자값 분리
5. 명명에서 사용 1) _이름 (앞 1개)
2) 이름_ (뒤 1개)
3) __이름 (앞 2개)
4) __이름__ (앞뒤 2개)

 

01 Interpreter에서 사용

  • 파이썬 Interpreter에서 가장 마지막 표현식의 결과값은 자동적으로 "_" 변수에 저장됨
  • "_"에 저장된 값을 다른 변수에도 저장 가능 
  • 일반적인 변수로도 사용 가능
>>> 5 + 4
9            # 위 표현식의 결과값인 9는 자동적으로 _에 저장됨
>>> _        
9
>>> _ + 6
15
>>> _
15
>>> a = _    # _의 값을 a 변수에 저장
>>> a
15

02 무시하는 값

  • 무시하는 값으로 사용 가능
  • unpacking 시 특정 값을 사용 안하고 싶은 경우 _에 할당 가능
  • 무시한다는 의미는 _에 값을 할당하고 이 값을 후에 사용하지 않는다는 의미
# Unpacking 시 값 무시
a, _, b = (1, 2, 3) # a = 1, b = 3
print(a, b)

# Extended Unpacking 시 여러 값 무시
# *(변수)는 unpacking 시 특정 변수에 여러 값들을 list로 할당할 때 사용 (i.e., Extended Unpacking)
a, *_, b = (7, 6, 5, 4, 3, 2, 1)
print(a, b)

03 Loop에서 사용

  • loop에서 변수로 사용 가능
# 3 번 loop하기
for _ in range(3):
    print(_)

# list interate하기
languages = ["Python", "JS", "Java", "C"]
for _ in languages:
    print(_)

_ = 1
while _ < 5:
    print(_, end = ' ') # end의 기본값인 '\n'를 ' '로 바꿈
    _ += 1

04 숫자값 분리

  • 길이가 긴 숫자 표현 시 가독성을 위해 자릿수 구분 표시할 때 사용 가능
  • 2진수(바이너리), 8진수, 16진수 표현도 구분하여 표시할 때 사용 가능
million = 1_000_000          # 긴 숫자
binary = 0b_0010             # 2진수
octa = 0o_64                 # 8진수
hexa = 0x_23_ab              # 16진수

print(million, binary, octa, hexa)

>>> addr = 0xCAFE_F00D 
>>> print(addr) 
3405705229
>>> amount = 10_000_000.0
>>> print(amount) 
10000000.0

05 명명

1. _이름

  • 변수, 함수, 또는 메소드 앞에 _ 붙일 경우 클래스가 원할 시 수정이 가능한 내부 사용용(internal use only, non-public)으로 간주
  • 즉, from ~ import * 시 _로 시작하는 변수/함수/메소드는 import 안 됨
  • 그러나 __all__에 지정되어 있다면 해당 모듈로부터 직접적으로 불러올 수 있음 (Python does not specify truly private so this one can be called directly from other modules if it is specified in __all__)
class Test:
    def __init__(self):
        self.name = "datacamp"
        self._num = 7
obj = Test()
print(obj.name)
print(obj._num)

  • 위와 같이 변수명 앞에 _를 붙였다고 해서 해당 변수에 접근하지 못하게 되진 않으나 다음과 같이 모듈을 import해서 쓰는 경우 효과가 발생 
# my_functions.py 내용

def func():
    return "hello"
    
def _private_func():
    return "no longer private?"
  • 위의 my_functions.py를 가져오기 위해 from my_functions import * 사용 시 다음과 같이 _private_func()는 import 불가능
>>> from my_functions import *
>>> func()
'hello'
>>> _private_func()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '_private_func' is not defined

  • 그러나 my_functions.py 모듈 자체를 import 시 사용 가능
>>> import my_functions
>>> my_functions.func()
'hello'
>>> my_functions._private_func()
'no lonager private?'

2. 이름_

  • 파이썬 키워드 (class, def와 같인 keyword)에 해당하는 이름을 변수/함수/클래스명으로 사용 시 이름 뒤 _를 붙여서 사용 가능
  • 즉, 파이썬 키워드와 겹치는 것을 방지하기 위해 사용
>>> def function(class):
  File "<stdin>", line 1
    def function(class):
                 ^^^^^
>>> def function(class_):
...     pass
...
>>>

3. __이름

  • 'name mangling'
  • mangle: '짓이기다,' '알아보기 힘든 모양으로 만드는 것'
  • 파이썬 interpreter에게 해당 서브클래스의 attribute 이름을 바꿔 이름 충돌이 나지 않게끔 하는 것 (leading double underscore tells the Python interpreter to rewrite the name in order to avoid conflict in a subclass)
  • __를 붙여 변수 생성 시 앞에 '_클래스명'이 붙어서 변수명이 지어짐
  • 주 목적은 클래스 내에서만 해당 변수/메소드를 사용하는 것이지만 public하게 만들기도 가능
# testFile.py 내용
class Myclass():
    def __init__(self):
        self.variable = 'no underscore'
        self._variable = 'one underscore'
        self.__variable = 'two underscore'
  • Python Interpreter에서 불러올 시:
>>> import testFile
>>> obj = testFile.Myclass()
>>> obj.variable
'no underscore'
>>> obj._variable 
'one underscore'
>>> obj.__variable 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Myclass' object has no attribute '__variable'. Did you mean: '_variable'?
>>> obj._Myclass__variable 
'two underscore'

  • public하게 만들어서 class 밖에서 사용하려면 다음과 같이 실행
class Myclass():
    def __init__(self):
        self.__variable = 10
 
    def func(self):
        print(self.__variable)
  • Python Interpreter에서 실행 시:
>>> import testFile
>>> obj = testFile.Myclass()
>>> obj.func()
10

4. __이름__

  • 'magic methods' or 'dunder methods (double underscore)'
    • magic methods: __init__, __add__, __len__, __repr__, 등
      • __init__: 생성자. 호출 없이 초기화 시 호출되는 함수, 클래스의 인스턴스가 생성될 때 실행되게 됨
      • __repr__: 해당 클래스 출력 시 내부적으로 호출되는 메소드 (Java의 toString() 함수와 유사) 
  • 사용자에 따라 연산자 오버로딩 (operator overloading)으로 사용하게끔 하기 위해 제공되는 방법
  • 사용자-정의 함수와 모듈의 함수를 구분하기 위해 사용됨
class Myclass():
    def __add__(self, a, b):
        print(a * b)
  • Python Interpreter에서 불러올 시:
>>> import testFile
>>> obj = testFile.Myclass()
>>> obj.__add__(1, 2)
2
>>> obj.__add__(2, 5)
10

참조

  1. https://www.datacamp.com/tutorial/role-underscore-python
  2. https://www.geeksforgeeks.org/underscore-_-python/ 
  3. https://eine.tistory.com/entry/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C-%EC%96%B8%EB%8D%94%EB%B0%94%EC%96%B8%EB%8D%94%EC%8A%A4%EC%BD%94%EC%96%B4-%EC%9D%98-%EC%9D%98%EB%AF%B8%EC%99%80-%EC%97%AD%ED%95%A0 
  4.  
  5.