파이썬으로 작성된 코드를 보다보면 함수 인자에 *args
, **kwargs
라는 생소한 인자가 들어간다. 이 키워드들이 어떤 것인지, *
가 무엇을 의미하는지 확인해본다.
packing/unpacking
packing은 여러 인자를 하나의 값으로 묶어주는 기능이다. 함수 인자의 이름 앞에 *
를 붙여주면 된다.
x
def foo1(*args):
print("type", type(args))
print("value", args)
foo1(1, 2, 3, 4)
위 코드를 실행하면 아래와 같이 출력된다.
xxxxxxxxxx
type <class 'tuple'>
value (1, 2, 3, 4)
foo1
함수의 인자에 1, 2, 3, 4를 전달했으며 함수는 이 값들을 튜플의 형태로 가져온다. 따라서 인자의 갯수에 상관없이 함수를 호출할 수 있다.
unpacking은 packing과 반대로 하나의 값을 여러 인자로 나눈다. 여기서 하나의 값은 리스트, 튜플, 셋, 딕셔너리와 같이 여러 값들을 묶은 자료형을 나타낸다. 이 자료형들이 가진 값들의 원소 하나씩 풀어내는 것이다.
x
def foo2(a, b, c, d):
print(a, b, c, d)
l = [1, 2, 3, 4]
foo2(*l) # unpacking
foo2
는 4개의 인자를 가진 함수이다. 4개가 원소인 리스트 l
을 unpacking하여 foo2
를 호출한 것이다.
가변 인자
가변인자를 사용하는 함수를 작성해본다.
x
def log(message, *values):
if not values:
print(message)
return
value_str = ", ".join(str(x) for x in values)
print(f"{message}: {value_str}")
log("numbers", 1, 2, 3, 4)
log("hello world")
l = [5, 6, 7, 9]
log("list numbers", *l)
위의 log
함수는 가변인자 values
를 사용한다.
가변인자를 사용할 때 제너레이터를 전달할 경우 주의해야한다. 함수 호출시 튜플로 변환해야하기 때문에 인자의 제너레이터를 반복하게 되고 이는 많은 메모리를 소모할 수 있다.
키워드 인자
파이썬에서는 함수 호출시 키워드를 사용해 인자를 전달할 수 있다.
xxxxxxxxxx
def foo3(first, second):
print(f"f: {first}, s: {second}")
foo3(1, 2)
foo3(1, second=2)
foo3(first=1, second=2)
foo3(second=2, first=1)
함수를 호출할 때 인자의 이름=값
형식으로 인자의 값을 대입할 수 있다.
딕셔너리 자료형을 사용해서도 키워드 전달 방식으로 함수를 호출할 수 있다.
x
dic = {
"first": 1,
"second": 2,
}
foo3(**dic)
"""
기존 인자와 함께 사용할 수 있다.
"""
dic = {
"second": 2,
}
foo3(1, **dic)
dic = {
"first": 1,
}
foo3(second=2, **dic)
"""
여러 딕셔너리를 사용해 호출 가능하다.
"""
dic1 = {
"first": 1,
}
dic2 = {
"second": 2,
}
foo3(**dic1, **dic2)
foo3(**dic2, **dic1)
**
연산자는 딕셔너리의 값을 함수 인자에 대응하는 키에 대응하여 호출하게 한다.
함수의 인자에 **
연산자를 넣으면 아래와 같다.
xxxxxxxxxx
def kwpacking(**kwargs):
print(kwargs)
print(type(kwargs)
kwpacking(a=1, b=2, c=3)
xxxxxxxxxx
{'a': 1, 'b': 2, 'c': 3}
<class 'dict'>
인자로 딕셔너리를 전달할 때와는 반대로 인자의 **
는 호출되는 함수의 키워드 인자를 딕셔너리 형태로 변환해준다.
위에서 살펴본 *args
와 **kwargs
를 동시에 사용할 수 있다.
x
def foo4(p, *args, **kwargs):
print("param", p)
print("args", type(args), args)
print("kwargs", type(kwargs), kwargs)
foo4(1, 2, 3, a=1, b=2)
l = [2, 3]
foo4(1, *l, a=1, b=2)
dic = {
"a": 1,
"b": 2
}
foo4(1, 2, 3, **dic)
xxxxxxxxxx
// 세 번 호출한 foo4는 모두 동일한 내용을 출력
param 1
args <class 'tuple'> (2, 3)
kwargs <class 'dict'> {'a': 1, 'b': 2}
인자 p
이외의 인자들은 *args
를 통해 튜플 형태로 전달되고, 키워드 인자들은 **kward
에서 딕셔너리 형태로 전달된다.
Ref
- 파이썬 코딩의 기술
- https://wikidocs.net/22801