*args는 남는 위치 인자(positional argument)를 튜플로, **kwargs는 남는 키워드 인자(keyword argument)를 딕셔너리로 모아 받는 문법이다. 반대로 호출할 때 *·**를 쓰면 시퀀스·딕셔너리를 개별 인자로 펼친다. 모으는 것을 패킹(packing), 펼치는 것을 언패킹(unpacking)이라 한다.
def log(level, *args, sep=" ", **kwargs):
print(level, sep.join(map(str, args)), kwargs)
log("INFO", "user", 42, sep="|", request_id="abc")
# INFO user|42 {'request_id': 'abc'}
nums = [1, 2, 3]
opts = {"sep": ", "}
print(*nums, **opts) # 1, 2, 3매개변수 순서
def f(a, b=1, *args, c, d=2, **kwargs): ...
# 위치 기본값 가변 키워드 전용 가변 키워드- 일반 매개변수 → 기본값 매개변수 →
*args→ 키워드 전용 매개변수 →**kwargs *args뒤에 오는 매개변수는 이름으로만 넘길 수 있다(키워드 전용, keyword-only). 가변 인자가 필요 없으면*만 써서 키워드 전용을 강제한다:def connect(host, *, timeout=5)/앞의 매개변수는 위치로만 넘길 수 있다(위치 전용, positional-only, 3.8+)- 기본값은 정의할 때 한 번만 평가된다. 리스트 같은 변경 가능한 값을 기본값으로 쓰지 않는다(가변 기본 인자 함정)
시퀀스 언패킹(sequence unpacking)
a, b = b, a # 교환
first, *rest = [1, 2, 3, 4] # first=1, rest=[2, 3, 4]
for name, score in zip(names, scores): ...
merged = {**defaults, **overrides} # 딕셔너리 합치기, 뒤가 이김쓰임
- 받은 인자를 그대로 다른 함수에 넘기는 래퍼·데코레이터
- 협력적 다중 상속에서 각 클래스가 필요한 인자만 꺼내고 나머지를
super()로 넘기기(파이썬 MRO와 super()) - 플래그성 인자를 키워드 전용으로 만들어 호출부를 읽기 쉽게 하기(플래그 인수)
**kwargs로 아무거나 받으면 잘못된 이름이 조용히 무시되기 쉽다. 받을 인자가 정해져 있다면 이름을 명시하고, 많아지면 매개변수 객체로 묶는다(매개변수 객체 만들기). 자바스크립트의 나머지 매개변수(rest parameters)·전개 문법(spread syntax)과 거의 같다.
출처: Python 튜토리얼: Arbitrary Argument Lists · Special parameters · Unpacking Argument Lists