Profile picture

[Python] 패킹(Packing), 언패킹(Unpacking), *args, **kwargs 가이드

JaehyoJJAng2024년 06월 10일

개요

파이썬에서의 Packing, Unpacking, *args, **kwargs

함수 호출, 정의 및 데이터 조작에서 자주 사용되는 개념이다.

이번 게시글에서는 해당 키워드들의 개념과 사용 방법을 기록해보려고 한다.


매개변수

기본값 매개변수

함수를 호출할 때 인자의 값을 지정하지 않고 호출해도 이미 함수 매개변수에 값이 명시되어 있는 상태이기 때문에 값을 따로 넘겨 받지 않아도 된다

def person(name: str = 'Doosik', age: int = 30) -> None:
    print(f'name: {name} , age: {age}')

person()

하지만 함수를 호출 할 때 인자를 명시해준다면 순서대로 값이 대입된다.

def person(name: str = 'Doosik', age: int = 30) -> None:
    print(f'name: {name} , age: {age}')

person('doo',35)

인자

위치 인자

기본적인 형태는 함수가 호출될 때 인자값을 순서대로 매개변수로 넘겨 받는다.

def person(name: str,age: int) ->  None:
    print(f'name: {name} , age: {age}')

person('doosik',30)

키워드 인자

함수를 호출 할 때 미리 인자와 매개변수를 명확하게 정해서 넘겨주는 방법이다.

def person(name: str, age: int) -> None:
    print(f'name: {name} , age: {age}')

person(age=30,name='doosik')

이렇게 순서에 상관없이 값을 넘길 수 있고 가독성 또한 우수하다.


위치 인자 vs 키워드 인자

만약 위치 인자(Positional Argument)와 키워드 인자(Keyword Argument)를 함께 쓴다면 어떻게 될까?

def person(name: str,age: int) -> None:
    print(f'name: {name} , age: {age}')

person(age=30,'doosik')
Traceback (most recent call last):
File "python", line 6
SyntaxError: positional argument follows keyword argument

위와 같은 오류가 발생한다.

키워드 인수의 경우 명확히 매개변수로 받을 인자값을 지정해주기 때문에 순서에 상관없이 작성할 수 있지만,

위치 인수의 경우 순서를 지켜줘야 하기 때문에 에러가 발생하게 된다.


*args

  • *args는 임의의 갯수의 위치 인수(Positional Argument)이다. 즉, 인수가 아무리 많아도 *args 매개변수로 받을 수 있다.
  • *args 매개변수가 선언되면 모든 인자들은 함수내부에서 tuple 형태로 반환된다.

def func_var_args(*args) -> None:
    print(args)

func_var_args("hello","Itsme","Bye")
# 출력결과

("hello","Itsme","Bye")

반대로 함수 또는 생성자가 여러 개의 인자를 받아야하는 상황에서 아래와 같이 사용할 수 있다

def login(_id: str, _pw: str) -> str:
    return f'id: {_id}, pw: {_pw}'

login_data: tuple[str] = ('id1234','pw1234')
login(*login_data)

에러 발생 예시

def func_var_args(name: str, *args: tuple[str], age: int) -> None:
    print(f'name: {name}, age: {age}, args: {args}')

func_var_args('doosik','arg1','arg2','arg3',30)

만약 *args 매개변수가 중간에 선언될 경우 뒤에 위치한 모든 매개변수를 tuple 형태로 받기 때문에

age 매개변수에 값을 대입해줄 수 없어 오류가 발생한다.


그렇기 때문에 아래와 같이 수정하여 작성하도록 하자

def func_var_args(name: str, age: int , *args: tuple[str]) -> None:
    print(f'name: {name}, age: {age}, args: {args}')

func_var_args('doosik',30,'arg1','arg2','arg3')

**Kwargs

  • kwargs는 임의의 갯수의 키워드 인수(keyword argument)이다. args와 마찬가지로 인자가 아무리 많더라도 모두 매개변수로 받아올 수 있다.
  • args와 다른점은 kwargs는 함수 내부에서 인자들을 dictionary 형태로 처리함

def func_with_kwargs(**kwargs) -> None:
    print(kwargs)

func_with_kwargs(requests=['0','안녕하세요'],name='wtt',age=25,job=None)
# 출력 결과

{'requests': ['0','안녕하세요'], 'name': 'wtt', 'age': 25, 'job': None}

❗️ 중요

위치 인수(Positional Argument)가 제일 먼저 위치해야 하고,

그다음 키워드 인수, *args , **kwargs 순으로 인자를 받아야 함

def mixed_params(age: int, name: str='아이유', *args, **kwargs) -> None:
    print()

mixed_params(20,'doosik','arg1','arg2',kwargs1='test1',kwargs2='test2')

Packing

Packing은 여러 값을 하나의 변수에 묶는 과정이다. 주로 ***를 사용하여 함수 정의 시 가변 개수의 인수를 받을 때 활용된다.


1. 리스트/튜플에서의 Packing

def pack_example(*args):
    print("Packed:", args)

pack_example(1, 2, 3, 4)  # Packed: (1, 2, 3, 4)

여기서 args는 전달된 모든 인수를 튜플로 묶는다.


2. 딕셔너리에서의 Packing

def pack_example(**kwargs):
    print("Packed:", kwargs)

pack_example(a=1, b=2, c=3)  # Packed: {'a': 1, 'b': 2, 'c': 3}

여기서 kwargs는 키워드 인수들을 딕셔너리로 묶는다.


Unpacking

Unpacking은 하나의 변수에 묶인 값들을 개별 값으로 풀어내는 과정이다.

이 방법또한 ***를 사용하여 리스트, 튜플, 딕셔너리 등을 분해한다.


1. 리스트/튜플에서의 Unpacking

numbers = [1, 2, 3]
a, b, c = numbers  # a=1, b=2, c=3

# 함수 호출 시
def add(a, b, c):
    return a + b + c

print(add(*numbers))  # 6

리스트 numbers*로 풀어서 함수에 전달한다.


2. 딕셔너리에서의 Unpacking

data = {'x': 10, 'y': 20}

def multiply(x, y):
    return x * y

print(multiply(**data))  # 200

딕셔너리 data**로 풀어서 함수에 전달한다.


*와 **의 일반적인 사용 예시

  • *는 리스트나 튜플을 Packing/Unpacking 할 때
  • **는 딕셔너리를 Packing/Unpacking 할 때

예제

def example(a, b, *args, **kwargs):
    print("a:", a)
    print("b:", b)
    print("args:", args)
    print("kwargs:", kwargs)

example(1, 2, 3, 4, 5, name="Alice", age=30)
# a: 1
# b: 2
# args: (3, 4, 5)
# kwargs: {'name': 'Alice', 'age': 30}
  • *args: 추가 위치 인수는 튜플로 묶인다.
  • **kwargs: 추가 키워드 인수는 딕셔너리로 묶인다.

Packing과 Unpacking을 혼합하여 사용하기

함수 정의와 호출 시 Packing과 Unpacking을 혼합하여 사용해보자.

def example(a, b, *args, **kwargs):
    print("a:", a)
    print("b:", b)
    print("args:", args)
    print("kwargs:", kwargs)

# 호출 시
args_list = [3, 4, 5]
kwargs_dict = {'name': 'Bob', 'age': 25}

example(1, 2, *args_list, **kwargs_dict)
# a: 1
# b: 2
# args: (3, 4, 5)
# kwargs: {'name': 'Bob', 'age': 25}

Loading script...