본문 바로가기

PYTHON

[Python / 파이썬 ] 파라미터 앞 (*args, **kwargs)

많은 파이썬 프로그래머 입문자들이 *args와 **kwargs라는 멋진 변수에서 헤맵니다. 그래서 뭘까요? 먼저 꼭 *args **kwargs 라는 이름으로 사용할 필요는 없다고 알려드리고 싶습니다. *별표만 꼭 사용하면 됩니다. *var, **vars로 사용하셔도 됩니다. *args **kwargs는 관례처럼 사용할 뿐입니다. *args부터 먼저 살펴봅시다.

 

 

*args   => agruments 의 줄임말 !

 ? 파라미터를 몇개를 받을지 모르는 경우 사용합니다.

    인자가 하나도 안 들어오는 경우도, 10개, 100개가 들어오는 경우도 수용해 줍니다.

    args 는 함수의 파라미터를 튜플로 저장하고 있습니다.

    하나의 인자를 전달 받고, *args를 통해 가변길이 인자를 전달 받습니다.

    전달받은 인자들은 함수내에서 list처럼 다룰 수 있습니다. 

 

   또한 아래 코드처럼, 인자들을 미리 정의한 후 전달할 수도 있습니다.

   이를 통해 파라미터 정의부 함수 실행부를 분리할 수 있다는 장점이 있습니다.

   조금 더 깔끔하게 파이썬 코드를 관리할 수 있겠죠.

 

**kwargs   => keyword agruments 의 줄임말 !

 ? 함수가 이름이 지정된 인자를 처리할 때 사용해야합니다.

  함수의 파라미터를 딕셔너리 형태로 저장하고 있습니다.

 

1. *args 부터 살펴봅시다

def print_param(*args): 
	print args 
    for p in args: 
    	print p 
        
print_param('a', 'b', 'c', 'd') 

#('a', 'b', 'c', 'd') 
#a 
#b 
#c 
#d

대부분 *args와 **kwargs는 함수를 정의 할 때 사용됩니다. *args와 **kwargs는 가변 갯수의 인자들을 함수에 넣어줍니다. 여기서 가변 갯수의 인자라 함은, 사용자들이 얼마나 많은 인자들을 함수에 넣을지 모르는, 즉 갯수가 변할 수 있는 상황에서 *args와 **kwargs를 사용할 수 있다는 뜻입니다.
*args는 키워드 되지않은 가변 갯수의 인자들을 함수에 보낼 때 사용합니다. 

 

2. **kwargs도 살펴봅시다

def print_param2(**kwargs): 
	print kwargs 
    print kwargs.keys() 
    print kwargs.values() 
    for name, value in kwargs.items(): 
    	print "%s : %s" % (name, value) 
print_param2(first = 'a', second = 'b', third = 'c', fourth = 'd') 

#{'second': 'b', 'fourth': 'd', 'third': 'c', 'first': 'a'} 
#['second', 'fourth', 'third', 'first'] 
#['b', 'd', 'c', 'a'] 
#second : b 
#fourth : d 
#third : c 
#first : a

**kwargs는 키워드된 가변 갯수의 인자들을 함수에 보낼 때 사용합니다.(역주: 가장 큰 차이는 keyword이냐 nonkeyword이냐입니다.) **kwargs는 함수가 이름이 지정된 인자를 처리할 때 사용해야합니다.

 

3. 두개를 같이 쓴다면 ?

def print_param3(*args, **kwargs): 
	print args 
    print kwargs 
    
print_param3('a', 'b') 
#('a', 'b') 
#{} 

print_param3(third = 'c', fourth = 'd') 
#() 
#{'fourth': 'd', 'third': 'c'}

print_param3('a', 'b', third = 'c', fourth = 'd') 
#('a', 'b')
#{'fourth': 'd', 'third': 'c'}

4. 응용하기

def print_param4(a, b, c): 
	print a, b, c 
    
p = ['a', 'b', 'c'] 
print_param4(*p) 
#a b c 

p2 = {'c' : '1', 'a' : '2', 'b' : '3'} 
print_param4(**p2) 
#2 3 1

 

5. Decorator와 결합하여 사용하기(나중에 데코레이터 올릴게요)

 

*args와 **kargs는 decorator와 결합하여 사용하면 더 유용하게 사용할 수 있습니다. 예를 들어, 함수를 실행할 때, 그 함수의 이름을 출력하고 함수를 실행하는 decorator를 만든다고 해봅시다. 근데, decorator 함수에서는 함수의 인자를 지정해줘야하기 때문에 decoration하는 함수의 인자의 수가 모두 같아야합니다. 이럴 때, *args와 **kargs를 이용하면 decoration 하는 함수의 인자의 길이에 상관없이 decorator를 만들 수 있습니다. 

 

logging_decorator는 함수를 실행할 때, 그 함수의 이름을 출력하는 기능을 갖는 decorator입니다. 이 decorator 함수에 *args, **kargs를 지정하고 이것을 그대로 원래 함수로 넘겨주면 인자의 길이에 상관없이 decorator를 구현할 수 있습니다.

 

Decorator와 *args, **kargs 사용 예제

 

이 예제에서 squared_number와 add_number는 인자의 수가 다른데 이를 *args를 이용하여 해결하였습니다. 만약 *args를 활용하지 않는다면, 각각에 대하여 decorator를 만들어야하죠. 또한 마지막 함수(add_numbers) 의 경우 함수 안에 keword를 지정하고 있습니다. 또 함수 실행 시 **kargs 를 통하여 인자를 넘기는데, 이 때 decorator에서 **kargs를 정의해 놓으면 keworded arguments 들을 그대로 decoration 함수를 전달할 수 있기 때문에 가변길이 인자를 처리할 수 있게 됩니다.

 

 



출처: https://3months.tistory.com/347 [Deep Play]

출처: https://jhproject.tistory.com/109