인자가 몇 개나 올지 모를 때
대부분의 함수는 매개변수 개수가 정해져 있어요. 하지만 가끔 더 유연한 게 필요해요 — 메시지를 몇 개든 받는 로거, 받은 걸 그대로 다른 함수에 넘겨주는 래퍼, 호출자가 어떤 옵션을 쓸지 몰라도 설정을 받아주는 그리기 함수 같은 거요.
파이썬은 매개변수 목록에 두 개의 특별 표시로 이걸 처리해요: *args와 **kwargs.
*args는 위치 인자를 모아요
별표 한 개는 "추가 위치 인자를 튜플로 모아라"를 의미해요:
함수 안에서 args는 평범한 튜플이에요. 반복하거나, 인덱싱하거나, len()에 넘기거나, 슬라이싱할 수 있어요.
*args는 보통 이름 있는 매개변수와 같이 등장해요:
first가 첫 인자를 잡고, *rest가 그 뒤의 모든 것을 튜플로 묶어요.
**kwargs는 키워드 인자를 모아요
별표 두 개는 키워드 인자에 같은 일을 해서, dict로 묶어줍니다:
describe 안에서 kwargs는 평범한 dict예요. 키는 키워드 이름을 문자열로 담고 있고요.
둘을 함께 쓰기
한 함수에서 둘 다 쓸 수 있어요. 관례는 *args를 **kwargs보다 앞에 두는 거예요:
왼쪽에서 오른쪽으로 본 매개변수 전체 순서는:
- 일반 위치 매개변수(필수 또는 기본값 있음).
*args.- 키워드 전용 매개변수(
*args뒤에 오는 건 키워드로만 넘길 수 있어요). **kwargs.
title이 첫 위치 인자를 잡아요. 나머지 위치 인자는 tags에 들어가고요. draft는 키워드로 넘겨야 해요(*tags 뒤에 왔으니까요). 나머지 키워드 인자는 metadata에 모입니다.
호출하는 쪽에서 *와 **로 언패킹하기
별표는 _반대 방향_으로도 동작해요 — 시퀀스나 dict를 호출의 인자들로 펼쳐 넣는 거예요:
인자 전달(포워딩) 에 엄청나게 편해요:
wrapped는 log가 어떤 인자를 기대하는지 알 필요가 없어요. 그냥 모든 걸 받아서 그대로 넘겨주거든요. 이 패턴은 데코레이터(더 고급 주제)나 래퍼 함수에서 정말 자주 등장합니다.
*args와 **kwargs가 틀린 선택일 때
쉽게 들떠서 아무 데나 쓰게 되는데, 경고 두 가지:
함수가 뭘 기대하는지 숨겨져요
코드베이스의 모든 함수가 def f(*args, **kwargs)라면, 호출하는 코드는 어떤 인자가 유효한지 전혀 알 수 없어요. 가능하면 이름 있는 매개변수를 쓰고, *args/**kwargs는 진짜로 가변 인자를 받거나 순수하게 전달하는 경우에만 쓰세요.
에러 메시지가 흐려져요
오타 난 키워드 이름이 호출 지점에서 바로 "unexpected keyword argument"로 뜨지 않고, 함수 안 깊은 곳에서 조용히 None이 되거나 KeyError로 나타나요. 이름 있는 매개변수가 훨씬 나은 피드백을 줍니다.
원칙: 기본은 이름 있는 매개변수, 함수가 진짜로 유연해야 하거나 다른 호출 가능한 것에 인자를 전달하는 경우에만 *args/**kwargs를 꺼내세요.
작은 실용 예제
기본값을 얹어서 서드파티 함수를 감싸는 그리기 스타일의 헬퍼:
*values가 호출자가 몇 개든 아이템을 넘길 수 있게 해주고, **style이 모든 옵션을 개별 매개변수로 선언할 필요 없이 추가 설정을 받아줘요. 유연하지만 불투명하진 않아요 — 안쪽 로직이 style에서 어떤 키를 읽는지 정확히 알려주거든요.
요약
*args는 추가 위치 인자를 튜플로 묶어요.**kwargs는 추가 키워드 인자를 dict로 묶어요.- 호출 쪽에서
*seq와**dict는 반대 방향으로 언패킹합니다. - 매개변수 순서: 일반 →
*args→ 키워드 전용 →**kwargs. - 과용하지 마세요 — 쓸 수 있을 때는 이름 있는 매개변수가 더 명확해요.
다음은 lambda입니다. 한 줄짜리 일회용 함수를 인라인으로 쓰는 방법이에요.
자주 묻는 질문
파이썬의 *args가 뭔가요?
*args는 추가로 들어오는 위치 인자들을 튜플로 모아요. def f(*args):라고 해두면 f(1, 2, 3)이라고 불렀을 때 args가 (1, 2, 3)이 됩니다. args라는 이름은 관례예요 — 뭐라고 불러도 되지만 다들 *args를 씁니다.
파이썬의 **kwargs가 뭔가요?
**kwargs는 추가 키워드 인자를 dict로 모아요. def f(**kwargs):라고 해두면 f(name='Ada', age=30)을 호출했을 때 kwargs가 {'name': 'Ada', 'age': 30}이 돼요. *args와 **kwargs를 함께 쓰면 함수가 어떤 인자 조합이든 받을 수 있어요.
꼭 args와 kwargs라고 이름을 지어야 하나요?
아니요. 별 표시가 중요한 거지 이름이 중요한 게 아니에요. *values와 **options도 똑같이 동작해요. 하지만 파이썬 코드에서는 args와 kwargs가 거의 보편적인 관례예요 — 더 설명적인 이름이 꼭 필요한 경우가 아니라면 이 관례를 따르세요.