Python 중고급 속성 정리 (3) 가변길이 인수목록 받기(*args, **kargs)
이번 포스팅에서는 알아두면 정말 유용한 가변길이 인수목록 받기를 정리해보겠습니다. 파이썬 코드를 보다보면 가끔 *args, **kargs를 보실 수 있습니다. 이것은 함수의 인자(parameter 또는 arguments)가 가변 길이일 때 사용합니다. args, kargs는 원하는 이름대로 쓸 수 있고, *, **는 각각 non-keworded arguments, keworded arguments를 뜻합니다.
예를 들어 아래 파이썬 코드를 보시면 쉽게 이해하실 수 있습니다.
*args
def test_var_args(f_arg, *args): print("first normal arg:", f_arg) for arg in args: print("another arg through *argv:", arg) test_var_args('yasoob', 'python', 'eggs', 'test')
first normal arg: yasoob
another arg through *argv: python
another arg through *argv: eggs
another arg through *argv: test
f_arg를 통해 하나의 인자를 전달 받고, *args를 통해 가변길이 인자를 전달 받습니다. 전달받은 인자들은 함수내에서 list처럼 다룰 수 있습니다.
또한 아래 코드처럼, 인자들을 미리 정의한 후 전달할 수도 있습니다. 이를 통해 파라미터 정의부와 함수 실행부를 분리할 수 있다는 장점이 있습니다. 조금 더 깔끔하게 파이썬 코드를 관리할 수 있겠죠.
param = ['yasoob', 'python', 'eggs', 'test'] test_var_args('hi', *param)
*kargs
다음으로는 **, 별표가 2개 붙은 keworded argments 사용법입니다. **kwargs로 전달받은 인자는 함수 내에서 dictionary 처럼 다룰 수 있습니다.
def greet_me(**kwargs): print(kwargs.items()) for key, value in kwargs.items(): print("{0} = {1}".format(key, value)) greet_me(name="yasoob", school="snu")
dict_items([('name', 'yasoob'), ('school', 'snu')])
name = yasoob
school = snu
kwargs = {"name": 'yasoob', 'school' :"snu"} greet_me(**kwargs)
이런식으로 dict로 미리 정의한 후에 ** 를 통해 함수의 인자로 넘길 수 있습니다. 매우 유용하죠.
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 함수를 전달할 수 있기 때문에 가변길이 인자를 처리할 수 있게 됩니다.
from functools import wraps def logging_decorator(f) : @wraps(f) def wrapper_function(*args, **kargs) : print(f.__name__ + " was called") print("결과 : ", f(*args, **kargs)) return wrapper_function @logging_decorator def square_number(x) : return x**2 square_number(2) @logging_decorator def add_number(x,y,z=0) : return x+y add_number(2,3) @logging_decorator def add_numbers(x=3, y=4) : return x+y add_numbers() kwargs = {"x": 3, "y": 5} add_numbers(**kwargs)
square_number was called
결과 : 4
add_number was called
결과 : 5
add_numbers was called
결과 : 7
add_numbers was called
결과 : 8
'Tools > Python' 카테고리의 다른 글
Python PEP8 code convention (1) | 2019.03.25 |
---|---|
Python PDPbox 패키지 설치시 문제 해결 (0) | 2018.12.20 |
Python 중고급 속성 정리 (2) Decorator - 기초 (0) | 2018.10.22 |
Python 중고급 속성 정리 (1) map, filter, reduce (3) | 2018.10.10 |
나만의 주피터 노트북 환경을 만들어보자 (nbextension, jupyter-theme) (0) | 2018.10.04 |