WeniVooks

검색

견고한 파이썬

args, kwargs

아규먼츠(args), 키워드 아규먼츠(kwargs)는 가변 아규먼트 또는 가변 매개변수, 키워드 가변 아규먼트 또는 키워드 가변 매개변수로 부릅니다. 여기서는 복수형 발음 그대로 아규먼츠와 키워드 아규먼츠로 부르도록 하겠습니다.

애스터리스크(*) 1개는 튜플이나 리스트를 패킹, 언패킹하는데 사용하며 2개는 딕셔너리를 패킹, 언패킹 하는데 사용됩니다. 변수명은 꼭 args나 kwargs를 사용하지 않아도 작동됩니다.

1. *args

아규먼츠(*args)가 함수 내 파라미터로 사용되면 여러 아규먼트를 묶어 받을 수 있습니다. 아래 예제를 통해 좀 더 상세히 살펴보겠습니다.

def print_args(*args): print(args) # 출력: (100, True, 'Licat') print_args(100, True, 'Licat')

아규먼트로 전달된 값이 모두 하나에 변수에 묶인 것을 볼 수 있습니다. 이걸 패킹되었다고 합니다. 이렇게 패킹 된 값은 튜플로 묶인 것을 확인할 수 있습니다.

아래처럼 일반 파라미터와 함께 사용될 수 있습니다.

def print_args(a, b, *args): print(args) # 출력: ('Licat', 'hello', 10) print_args(100, True, 'Licat', 'hello', 10)

다만 이렇게 선언할 때에는 뒤에 일반 파라미터를 사용하지 않도록 해야 합니다. 다음 코드는 애러가 나는 코드입니다.

def print_args(a, b, *args, c): # *args뒤에 일반 변수를 선언하지 못합니다. print(args) print_args(100, True, 'Licat', 'hello', 10)

애스터리스크는 묶는 것과 푸는 것, 패킹과 언패킹에 모두 사용이 됩니다.

# 패킹 def func(*args): print(args) func(10, 20, 30) # 10, 20, 30 => *args => (10, 20, 30)
# 언패킹 def func(a, b, c): print(a, b, c) args = (10, 20, 30) func(*args) # (10, 20, 30) => *args => 10, 20, 30

두번째 예제에서 이미 튜플인 args 변수를 아규먼트 *args로 보냄으로 각각 a, b, c에 할당된 것을 확인할 수 있습니다.

2. kwargs

키워드 아규먼츠(kwargs)는 딕셔너리로 가변 아규먼트를 받을 수 있는 방법입니다. 아규먼츠(args)는 튜플 형식으로 아규먼트를 받는 반면 키워드 아규먼츠(kwargs)는 딕셔너리 형태로 아규먼트를 받습니다.

def print_kwargs(a, **kwargs): print(a) print(kwargs) print_kwargs(100, name='Licat', age='10')

여기서 에스터리스크를 1개만 사용하면 key만 넘어갑니다. key와 value 모두를 넘기기 위해 2개를 사용합니다.

def print_kwargs(*kwargs): print(kwargs) value = {'one':10, 'two':20} print_kwargs(*value)

아래 예시를 통해 좀 더 상세히 살펴보도록 하겠습니다.

def func(a=100, **kargs): print(a, kargs) func(1000, i=1, j=2, k=3) # a=1, b=2, c=3 => **kwargs => {'a': 1, 'b': 2, 'c': 3}
def func(d=100, c=200, b=300, a=400): print(d, c, b, a) kwargs = {'a': 1, 'b': 2, 'c': 3} func(**kwargs) # {'a': 1, 'b': 2, 'c': 3} => **kwargs => a=1, b=2, c=3

첫번째 예제에서는 패킹이 되는 과정을 두번째 예제에서는 언패킹 되는 것을 확인할 수 있습니다.

3. *args와 kwargs 응용

함수를 정의할 때 *argskwargs를 함께 사용하면, 함수는 다양한 형태의 인자들을 유연하게 받을 수 있습니다. 이때, 일반적으로 \*args를 먼저 위치시킨 후, 그 다음에 kwargs를 위치시킵니다. 주의할 점은 인자를 전달할 때, 위치 인자들은 항상 키워드 인자들 앞에 와야 합니다. 그렇지 않으면 파이썬은 에러를 발생시킵니다. 그리고 키워드 인자들은 명시적으로 이름을 지정해서 전달해야 합니다.

다음 예제는 *argskwargs 를 둘다 사용하여 적용한 여러 예시입니다. 마지막 코드에서 중간에 ‘Licat’이라는 위치인자가 순서가 섞여있었기 때문에 에러가 발생합니다.

def print_args_kwargs(*args, **kwargs): print('args:', args) print('kwargs:', kwargs) print_args_kwargs(100, True, 'Licat') print('--------') print_args_kwargs(score=100, name='Licat', age='10') print('--------') print_args_kwargs(100, True, 'Licat', score=100, name='Licat', age='10') print('--------') # print_args_kwargs(100, score=100, True, name='Licat', 'Licat', age='10') # error
# 출력
args: (100, True, 'Licat')
kwargs: {}
--------
args: ()
kwargs: {'score': 100, 'name': 'Licat', 'age': '10'}
--------
args: (100, True, 'Licat')
kwargs: {'score': 100, 'name': 'Licat', 'age': '10'}
--------
# 출력
args: (100, True, 'Licat')
kwargs: {}
--------
args: ()
kwargs: {'score': 100, 'name': 'Licat', 'age': '10'}
--------
args: (100, True, 'Licat')
kwargs: {'score': 100, 'name': 'Licat', 'age': '10'}
--------

아래 예제는 미리 선언한 inputlist와 inputdic의 파라미터의 값을 선언해서 보내는 형식으로 구성되어 있습니다.

def print_args_kwargs(*args, **kwargs): print('args:', args) print('kwargs:', kwargs) inputlist = [100, True, 'leehojun'] inputdic = {'score':100, 'name':'leehojun', 'age':'10'} print_args_kwargs(*inputlist) print('--------') print_args_kwargs(**inputdic) print('--------') print_args_kwargs(*inputlist, **inputdic)
args: (100, True, 'leehojun')
kwargs: {}
--------
args: ()
kwargs: {'score': 100, 'name': 'leehojun', 'age': '10'}
--------
args: (100, True, 'leehojun')
kwargs: {'score': 100, 'name': 'leehojun', 'age': '10'}
args: (100, True, 'leehojun')
kwargs: {}
--------
args: ()
kwargs: {'score': 100, 'name': 'leehojun', 'age': '10'}
--------
args: (100, True, 'leehojun')
kwargs: {'score': 100, 'name': 'leehojun', 'age': '10'}

4. 나아가기

4.1 * 연산자의 활용

파이썬에서 * 연산자는 여러 곳에서 다양한 방식으로 사용됩니다. 위에서는 *args를 통해 여러 개의 아규먼트를 하나의 파라미터에 담는 방법을 살펴보았습니다. 이번에는 할당문에서 * 연산자의 활용을 살펴보겠습니다.

파이썬에서는 여러 개의 값을 여러 개의 변수에 한 번에 할당할 수 있습니다. 이를 "언패킹"이라고 합니다. 그런데 할당하려는 값들의 수가 변수의 수보다 많다면, 일반적으로는 에러가 발생합니다. 이런 상황에서 * 연산자를 사용하면, 초과된 값들을 리스트로 묶어서 해당 변수에 할당할 수 있습니다.

예를 들어, 아래와 같은 코드를 생각해보겠습니다.

one, two, *three = 1, 2, 3, 4, 5 print(one, two, three)

이 코드에서 one에는 1이, two에는 2가 할당되고, 나머지 값들(3, 4, 5)은 리스트 형태로 three에 할당됩니다. * 연산자 덕분에 three 변수는 여러 개의 값을 한 번에 받을 수 있게 되었습니다.

이 기능은 데이터를 동적으로 처리할 때, 특히 어떤 데이터 그룹을 별도로 처리해야 할 때 유용하게 사용됩니다.

이 기법은 아래처럼 특정 문자를 제거하는 용도로도 사용할 수 있습니다.

a, b, *c = 'hello world' c # 출력: ['l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
4.2 강제 키워드 인자

파이썬 3버전에서는, *를 사용해 강제 키워드 인자를 정의할 수 있습니다. 이를 통해 몇몇 인자들은 반드시 키워드 인자로만 전달될 수 있도록 할 수 있습니다.

def func(a, b, *, c, d): print(a, b, c, d) func(1, 2, c=3, d=4) # 올바른 예시 # func(1, 2, 3, 4) # 잘못된 예시
4.3 중복된 키워드 인자

kwargs를 사용할 때, 다른 키워드 인자와 중복되는 키가 있는 경우 에러가 발생합니다. 이런 상황을 피하기 위해 주의가 필요합니다.

def func(a, b=10, **kwargs): print(a, b, kwargs) # func(1, b=20, c=30) # 에러: b가 중복으로 전달됨
{"packages":["numpy","pandas","matplotlib","lxml"]}
13.7 함수의 다른 형태 lambda13.9 이터레이터와 제너레이터