Python을 공부하다 보면 다음과 같은 코드를 자주 보게 됩니다.
inputs = tokenizer(text, return_tensors="pt")
outputs = model(**inputs)
처음 보면 **가 무슨 의미인지 이해하기 어렵습니다.
“
**는 곱하기도 아닌데 왜 붙어 있을까?”
이번 글에서는 Python의 언패킹(Unpacking) 개념부터 *와 **의 차이, 그리고 Hugging Face에서 model(**inputs)를 사용하는 이유까지 자세히 알아보겠습니다.
언패킹(Unpacking)이란?
언패킹(Unpacking)은 하나의 자료구조(List, Tuple, Dictionary)에 들어 있는 값을 꺼내서 함수의 인자로 전달하는 기능입니다.
Python에서는 두 가지 방법이 있습니다.
*: 리스트(Tuple 포함) 언패킹**: 딕셔너리(Dictionary) 언패킹
1. * : 리스트(Tuple) 언패킹
예를 들어 다음과 같은 함수가 있다고 가정해 보겠습니다.
def add(a, b):
return a + b
일반적으로는 다음과 같이 호출합니다.
add(3, 5)
하지만 이미 리스트 안에 값이 들어 있다면?
nums = [3, 5]
그대로 넣으면 오류가 발생합니다.
add(nums)
왜냐하면 함수는 인자를 두 개 필요로 하는데, 리스트 하나만 전달했기 때문입니다.
이럴 때 사용하는 것이 *입니다.
add(*nums)
Python은 내부적으로 다음과 같이 변환합니다.
add(3, 5)
즉,
*리스트
↓
첫 번째 값,
두 번째 값,
세 번째 값...
으로 자동 변환됩니다.
예제
def print_name(first, last):
print(first, last)
name = ["Hong", "GilDong"]
print_name(*name)
실제로는 다음과 같습니다.
print_name("Hong", "GilDong")
2. ** : Dictionary 언패킹
이번에는 Dictionary를 살펴보겠습니다.
def add(a, b):
return a + b
Dictionary가 다음과 같이 있다고 가정합니다.
params = {
"a": 3,
"b": 5
}
이때
add(**params)
라고 작성하면 Python은 내부적으로
add(
a=3,
b=5
)
로 변환합니다.
즉,
Dictionary의
Key → 함수의 매개변수 이름
Value → 실제 전달되는 값
이 됩니다.
*와 **의 차이
* | ** |
|---|---|
| List, Tuple | Dictionary |
| 위치 인자(Positional Argument) | 키워드 인자(Keyword Argument) |
| 순서대로 전달 | 이름으로 전달 |
예를 들어
nums = [1, 2, 3]
func(*nums)
↓
func(1, 2, 3)
반면
params = {
"a":1,
"b":2,
"c":3
}
func(**params)
↓
func(
a=1,
b=2,
c=3
)
Hugging Face에서는 왜 **를 사용할까?
Hugging Face의 Tokenizer는 결과를 Dictionary 형태로 반환합니다.
inputs = tokenizer(
"안녕하세요.",
return_tensors="pt"
)
출력 예시는 다음과 같습니다.
{
"input_ids": tensor(...),
"token_type_ids": tensor(...),
"attention_mask": tensor(...)
}
반면 BERT 모델의 forward() 함수는 대략 다음과 같이 정의되어 있습니다.
def forward(
self,
input_ids=None,
attention_mask=None,
token_type_ids=None
):
...
즉, 필요한 입력이 모두 키워드 인자입니다.
따라서
model(**inputs)
는 Python이 자동으로 다음과 같이 변환합니다.
model(
input_ids=inputs["input_ids"],
token_type_ids=inputs["token_type_ids"],
attention_mask=inputs["attention_mask"]
)
이렇게 작성하면 필요한 입력이 많아져도 코드를 간결하게 유지할 수 있습니다.
**kwargs는 무엇일까?
PyTorch 모델을 보면 다음과 같은 코드도 자주 등장합니다.
def forward(self, input_ids, **kwargs):
...
여기서 **kwargs는
“이 함수에 전달되는 추가적인 키워드 인자를 모두 Dictionary 형태로 받겠다.”
는 의미입니다.
args는 arguments의 줄임말이며, kwargs는 keyword arguments의 줄임말입니다.
예를 들어
model(
input_ids=x,
attention_mask=mask,
token_type_ids=token
)
이라면
kwargs
에는
{
"attention_mask": mask,
"token_type_ids": token
}
이 저장됩니다.
이를 통해 함수는 필요한 인자만 사용하고, 나머지는 유연하게 처리할 수 있습니다.
정리
Python의 *와 **는 언패킹을 위한 매우 중요한 문법입니다.
*는 리스트나 튜플을 위치 인자로 풀어 전달합니다.**는 Dictionary를 키워드 인자로 풀어 전달합니다.- Hugging Face와 PyTorch에서는 Tokenizer가 Dictionary를 반환하기 때문에
model(**inputs)와 같은 형태를 매우 자주 사용합니다. - 또한
**kwargs를 사용하면 다양한 추가 인자를 유연하게 처리할 수 있어, 라이브러리와 프레임워크에서 널리 활용됩니다.
처음에는 *와 **가 낯설게 느껴질 수 있지만, 원리를 이해하면 Python 코드의 가독성과 활용성이 크게 향상됩니다. 특히 머신러닝과 딥러닝 프레임워크를 사용할 때는 거의 필수적으로 접하게 되는 문법이므로 꼭 익혀두는 것을 추천합니다.

