개요
파이썬에서의 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}