|

파이썬 args kwargs 차이: *와 **로 함수 인자를 유연하게 받는 방법

파이썬 args kwargs 함수 인자 정리 대표 이미지
파이썬 *args와 **kwargs는 인자를 많이 받는 문법이 아니라, 호출 규칙을 유연하게 만드는 도구입니다.

args kwargs 문법은 파이썬 함수 인자를 유연하게 받을 때 자주 등장합니다. `*args`는 여러 위치 인자를 받고, `**kwargs`는 여러 키워드 인자를 받습니다.

하지만 핵심은 많이 받는 방법이 아니라 호출 규칙을 어디까지 열어둘지 정하는 것입니다. 이 글은 Python 공식 문서의 함수 호출 규칙을 기준으로 `*args`, `**kwargs`, unpacking, 실무 설계 기준을 단계적으로 정리합니다.

파이썬 args kwargs 차이 요약 카드
*args는 위치 인자를 tuple로, **kwargs는 키워드 인자를 dict로 받습니다.

파이썬 args kwargs를 이해하기 전에

함수 인자는 크게 위치 인자와 키워드 인자로 나눌 수 있습니다. 위치 인자는 순서로 전달되고, 키워드 인자는 이름으로 전달됩니다.

def send_message(to, text):
    print(f"{to}: {text}")

send_message("kim", "hello")
send_message(to="kim", text="hello")

`*args`와 `**kwargs`는 이 기본 규칙 위에 올라갑니다. 그래서 먼저 ‘위치로 들어오는 값’과 ‘이름으로 들어오는 값’을 구분해야 합니다.

*args는 남은 위치 인자를 모은다

함수 정의에서 `*args`를 쓰면, 명시적으로 받지 않은 위치 인자들이 tuple로 모입니다. 이름은 꼭 args일 필요는 없지만 관례적으로 args를 씁니다.

def total(*args):
    print(args)
    return sum(args)

print(total(1, 2, 3))

위 코드에서 `args`는 `(1, 2, 3)`입니다. 여러 값을 하나의 tuple로 받은 뒤 반복하거나 집계할 수 있습니다.

**kwargs는 남은 키워드 인자를 모은다

`**kwargs`는 명시적으로 받지 않은 키워드 인자를 dict로 모읍니다. 설정값, 옵션, 메타데이터처럼 이름이 중요한 값에 자주 쓰입니다.

def create_user(name, **kwargs):
    print(name)
    print(kwargs)

create_user("kim", age=30, role="admin")

이때 `kwargs`는 `{‘age’: 30, ‘role’: ‘admin’}`입니다. 키가 문자열이고, 값은 호출자가 넘긴 값입니다.

함수 정의와 함수 호출에서 별표 의미는 다르다

함수 정의에서 `*args`는 값을 모읍니다. 반대로 함수 호출에서 `*values`는 리스트나 tuple을 위치 인자로 펼칩니다. `**options`는 dict를 키워드 인자로 펼칩니다.

def connect(host, port, secure=False):
    print(host, port, secure)

values = ("localhost", 5432)
options = {"secure": True}

connect(*values, **options)

같은 별표라도 정의 쪽에서는 모으기, 호출 쪽에서는 펼치기라고 이해하면 덜 헷갈립니다.

args kwargs를 같이 쓰는 순서

Python 함수 정의에는 인자 순서 규칙이 있습니다. 일반적으로 명시 인자, `*args`, 키워드 전용 인자, `**kwargs` 순서로 읽으면 됩니다.

def request(method, url, *args, timeout=3, **kwargs):
    print(method, url)
    print(args)
    print(timeout)
    print(kwargs)

이 구조는 유연하지만, 처음 보는 사람이 함수 계약을 한눈에 읽기 어렵게 만들 수도 있습니다. 공개 API에서는 꼭 필요한 유연성인지 먼저 판단해야 합니다.

언제 쓰면 좋을까

  • 여러 값을 자연스럽게 집계하는 함수에는 `*args`가 어울린다
  • 옵션이 많고 일부만 넘기는 함수에는 `**kwargs`가 어울릴 수 있다
  • 다른 함수로 인자를 그대로 전달하는 wrapper에는 둘 다 자주 쓰인다
  • 라이브러리 확장 지점에서는 미래 옵션을 받기 위해 사용하기도 한다

언제 피하는 편이 좋을까

모든 인자를 `*args`, `**kwargs`로 받으면 함수가 무엇을 요구하는지 숨겨집니다. IDE 자동완성, 타입 힌트, 문서화, 테스트가 모두 불리해질 수 있습니다.

# 읽기 어려운 예
def save_user(*args, **kwargs):
    ...

# 계약이 더 분명한 예
def save_user(name: str, email: str, is_active: bool = True):
    ...

함수의 핵심 계약은 명시 인자로 드러내고, 정말 부가적인 확장 지점에만 kwargs를 쓰는 편이 좋습니다.

실무 체크리스트

  1. 함수가 반드시 받아야 하는 값은 명시 인자로 둔다
  2. 개수가 변하는 위치 값이면 `*args`를 검토한다
  3. 이름이 있는 선택 옵션이면 `**kwargs`를 검토한다
  4. wrapper 함수라면 넘기는 인자와 소비하는 인자를 분리한다
  5. 타입 힌트와 문서에서 kwargs의 허용 키를 설명한다

정리

파이썬 `*args`와 `**kwargs`는 함수 인자를 무제한으로 받기 위한 만능 문법이 아닙니다. 위치 인자와 키워드 인자를 모으거나 펼쳐서 호출 규칙을 유연하게 만드는 도구입니다.

Python 웹 코드에서 함수 인자 설계가 실제로 쓰이는 예는 FastAPI Depends 사용 기준, FastAPI JWT 인증은 어디서 나눠야 할까, Alembic autogenerate가 no changes detected를 내는 이유와 함께 보면 좋습니다. 외부 기준은 Python Tutorial – More on Defining Functions, Python Tutorial – Unpacking Argument Lists, Python Language Reference – Calls를 확인했습니다.

함께보면 좋은 글