본문 바로가기
Back-end/Python

[문법] 가변인자 - *args, **kwargs

by 허도치 2019. 12. 20.

  Python에서 함수를 사용하다보면 매개변수를 가변적으로 전달하여 처리할 때가 있다. 가장 대표적인 예가 옵션을 설정할 때이다. Positional Argument floor를 받고, Keyword Argument tv, bed, computer를 받는 예제 함수를 통해 알아보자.

1
2
3
4
5
6
7
8
9
10
11
12
def dochiHouse(floor, tv=None, bed=None, computer=None):
    house = f'아파트 {floor}층' if floor is not None else '단독주택'
 
    things = 0
    if tv is not None:
        things += tv
    if bed is not None:
        things += bed
    if computer is not None:
        things += computer
 
    print(f'우리 집은 {house}이고 {things}개의 가구가 있어')
cs

 

  위 함수를 실행해보자.

1
2
3
4
dochiHouse(9, tv=1, bed=1)
'''
우리 집은 아파트 9층이고 2개의 가구가 있어
'''
cs

  computer 변수를 생략했는데도 정상적으로 출력되는 것을 확인할 수 있다. computer 변수와 같이 초기값을 설정하는 경우 Keyword Argument로 인식하여 생략할 수 있지만, floor 변수와 같이 초기값이 없는 경우 Positional Argument로 인식하여 매개변수의 위치에 맞추어 반드시 입력해주어야 한다.

 

 

그럼 이번에는 새로운 변수( laptop )를 추가하여 다시 실행시켜 보자.

1
2
3
4
5
6
7
dochiHouse(9, tv=1, bed=1, laptop=1)
'''
Traceback (most recent call last):
  File "test.py", line 14, in <module>
    dochiHouse(9, tv=1, bed=1, laptop=1)
TypeError: dochiHouse() got an unexpected keyword argument 'laptop'
'''
cs

  오류가 발생하였다. 왜 그럴까? 매개변수로 지정된 변수 외에는 임의로 추가로 입력할 수 없기 때문이다. 위 예제에서는 laptop 변수는 함수에서 정의되지 않은 매개변수이므로 오류가 발생했다.

 

  지금은 4개의 매개변수를 갖는 함수이지만, 상황에 따라 사용해야 하는 옵션이 수십, 수백가지가 있을 수 있다. 하나의 함수에 이 모든 매개변수를 정의하는 것은 부적절한 방법이다.

 

  이때 사용하는 것이 가변인자(Variadic Parameters)이다.

 

  가변인자는 변수앞에 Asterisk(*) 문자를 사용한다. C언어에서는 변수앞에 *이 있으면 포인터 변수를 가리키지만 Python에서는 가변인자를 나타낸다. 이 문자가 1개인 경우 Positional Argument를 가리키며 주로 *args로 사용하고, 2개인 경우 Keyword Argument를 가리키며 주로 **kwargs를 사용한다.

 

 

  위에서 사용한 함수에 가변인자( *args, **kargs )를 추가해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def dochiHouse(floor, *args, tv=None, bed=None, computer=None, **kwargs):
    house = f'아파트 {floor}층' if floor is not None else '단독주택'
    
    things = 0
    if tv is not None:
        things += tv
    if bed is not None:
        things += bed
    if computer is not None:
        things += computer
 
    for key, value in kwargs.items():
        if key is not None:
            things += value
 
    print(f'우리 집은 {house}이고 {things}개의 가구가 있어')
cs

 

  그리고 이전 함수에서 실패했던 예제를 다시 실행시켜보자.

1
2
3
4
dochiHouse(9, tv=1, bed=1, laptop=1)
'''
우리 집은 아파트 9층이고 3개의 가구가 있어
'''
cs

  새로운 변수가 추가되어도 정상적으로 출력되는 것을 확인할 수 있다.

 

 

  이번엔 가변인자들을 확인해보자.

1
2
3
4
5
6
7
8
9
print( type(args), args )
'''
<class 'tuple'> ()
'''
 
print( type(kwargs), kwargs )
'''
<class 'dict'> {'laptop': 1}
'''
cs

  argsTuple이고 값이 비어있으며, kwargsDictionary이며 새로 추가한 변수가 들어있는 것을 확인할 수 있다.

 

 

 이번엔 값을 더 많이 추가해서 테스트 해보자.

1
2
3
4
dochiHouse(9'가''변''인''자', ac=2, tv=1, fan=5, bed=1, laptop=1)
'''
우리 집은 아파트 9층이고 10개의 가구가 있어
'''
cs

  이번에는 *args 변수 위치에 여러개의 Positional Argument를 추가하였고, Keyword Argument는 순서에 상관없이 입력 해보았는데 잘 돌아간다.

 

 

  이번에도 가변인자들을 출력해보자.

1
2
3
4
5
6
7
8
9
print( type(args), args )
'''
<class 'tuple'> ('', '', '', '')
'''
 
print( type(kwargs), kwargs )
'''
<class 'dict'> {'laptop': 1, 'ac': 2, 'fan': 5}
'''
cs

  args에는 floor 변수를 제외하고 새로 추가한 인자들이 순서대로 저장되어 있고, kwargs에는 새로 추가한 인자들이 정렬되어 있다.

 

 

  이상으로 가변인자에 대해서 알아보았다. 정리하자면 함수의 매개변수는 Positional Argument(PA)Keyword Argument(KA)가 있으며, 작성 순서는 PA, *PA, KW, **KW이다. *PA, KW, **KW, 는 함수 실행시 생략이 가능하지만 PA는 필수로 입력해야 한다. 함수를 생성할때 필수 입력값을 받아야 하는 경우에는 PA를 사용하고, 선택 입력값을 KW로 처리하도록 하자.

댓글