4. 가변길이 인수목록받기 args,kwargs

참고 사이트 : Intermediate python (http://book.pythontips.com/en/latest/)
참고 블로그 : https://3months.tistory.com/347?category=753896

*agrs 정의

  • *args : non-keyworded arguments로 요소 나열 or *리스트이 들어가 함수내부에서 리스트로 사용
    1) 함수 정의시 *를 붙혀서 인자로 만들고, 함수 내부에서는 리스트로 사용한다.
    2) 함수 호출시, 여러요소를 나열해서 넣어준다.
    3) 함수 호출시, 정의해논 리스트를 넣어줄려면 *를 붙혀서 넣어준다.

normal arg + *args

  • 함수호출시, 여러요소를 리스트처럼 나열해서 넣어 사용 ( [ ] 리스트는 넣으면 안됨)
In [2]:
def test_var_args(first_arg, *args):
    print('첫번째 변수 : ' , first_arg)
    
    for arg in args:
        print('*args 목록 : ', arg)
In [3]:
test_var_args('조재성', '김석영', '조재경', '조아라')
첫번째 변수 :  조재성
*args 목록 :  김석영
*args 목록 :  조재경
*args 목록 :  조아라

미리 만든 리스트를 * 붙혀서 전달하기

In [4]:
param = ['김석영', '조재경','조아라']
test_var_args('조재성', *param)
첫번째 변수 :  조재성
*args 목록 :  김석영
*args 목록 :  조재경
*args 목록 :  조아라

만약 안붙힌 리스트를 \args 자리에 전달하면?

  • 함수내부에서 리스트로서 사용이 안되고, 덩어리체 붙어있다
  • 나열해서 넣어주든지, *를 붙힌 리스트를 넣어준다
In [5]:
test_var_args('조재성', param)
첫번째 변수 :  조재성
*args 목록 :  ['김석영', '조재경', '조아라']

**kwargs의 정의

  • **kwargs : keyworded arguments로 key1=value1, key2=value2 의 요소 나열 or **딕셔너리이 들어가 함수내부에서 딕셔너리로 사용
    1) 함수 정의시 **를 붙혀서 인자로 만들고, 함수 내부에서는 딕셔너리로 사용한다.
    2) 함수 호출시, 여러 요소를 key1=value1 형태로 나열해서 넣어준다.
    3) 함수 호출시, 정의된 딕셔너리를 넣어줄려면 **를 붙혀서 넣어준다.
In [7]:
def greet_me(**kwargs):
    print('kwargs.items() : ',kwargs.items())
    for key, value in kwargs.items():
        print( f'{ key } (key) = { value } (value)')

key=value 형태로 요소를 나열하는 경우

In [8]:
greet_me(name = '조재성', 학교 = '동신대')
kwargs.items() :  dict_items([('name', '조재성'), ('학교', '동신대')])
name (key) = 조재성 (value)
학교 (key) = 동신대 (value)

미리 정의한 딕셔너리에 **를 붙혀 대입

In [9]:
kwargs = { 
         'name' : '조재성',
         '학교' : 'dsu'
}
greet_me(**kwargs)
kwargs.items() :  dict_items([('name', '조재성'), ('학교', 'dsu')])
name (key) = 조재성 (value)
학교 (key) = dsu (value)

만약 딕셔너리만 그대로 넣어버리면?

In [10]:
greet_me(kwargs)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-10-8adf3a7faafc> in <module>
----> 1 greet_me(kwargs)

TypeError: greet_me() takes 0 positional arguments but 1 was given
In [ ]:
 

decorator + 가변길이 인수목록(args, kwargs) 같이 사용하기

decorator복습

  1. decorator함수는 그것을 필요로하는 함수를 인자로 받아, 중복되는 내용과 함께 배치한다.
  2. 중복되는 내용을 decorator로 해결하고 싶은 함수는, @decorator함수 와 같이 정의한다.
  3. 함수를 실행해주면, decorator가 실행된다.

decorator의 문제점

  1. 데코당할 함수의 인자 개수가 같을 때만, 중복으로 사용할 수 있다.
  2. 만약, 함수1과 함수2의 인자 개수가 다를 때는, decorator를 반복해서 사용할 수 없다.

**kwargs 나 *args를 이용하여, 함수1과 함수2의 인자수가 다르더라도 반복해서 decorator를 사용할 수 있다.

  1. decorator로 들어오는 함수를 반복되는 내용으로 wrapper해주는 wrapper함수의 인자를 넣어준다-> 내부에서 중복내용과 배치되는, 들어오는 함수도 인자를 넣어준다.

    • 기존에는 들어오는 함수자체가 인자가 없는 함수를 넣어서 wrapper함수안에서도 함수의 인자 사용안하고 print만 했었다.
  2. func(*args, **kwargs)로 인자를 주면, 순서에 상관없이 *리스트**딕셔너리 아무거나 대입해서 알아서 처리되는 특징

    • 함수의 인자가 한개라도 알아서 처리된다.
    • 인자가 여러개 일 때는, *리스트나 **딕셔너리를 활용한다
    • 인자가 3개이더라도, 초기값만 설정되어있다면, 2개만 넣어줘도 알아서 처리된다.
In [20]:
# decorator 정의
def logging_decorator(func):
    def wrapper_function( *args, **kwargs):
        print( func.__name__ + " 함수가 호출되었습니다.")
        print( "함수호출 결과 : ", func(*args, **kwargs))
    return wrapper_function

# 함수1 정의 with 데코레이터 
@logging_decorator
def square_number(x):
    return x**2

# 함수2 정의 with 데코레이터 
@logging_decorator
def add_numbers(x=3, y=4):
    return x+y

# 함수3 정의 with 데코레이터 
@logging_decorator
def add_number(x, y, z=5):
    return x+y
In [4]:
add_number()
add_number 함수가 호출되었습니다.
함수호출 결과 :  7
In [5]:
# 인자가 한개라도 알아서 처리된다.
square_number(2)
square_number 함수가 호출되었습니다.
함수호출 결과 :  4
In [6]:
add_number(2, 3)
add_number 함수가 호출되었습니다.
함수호출 결과 :  5
In [17]:
# 인자가 여러개  일 때는, *리스트나 **딕셔너리를 활용한다

# 딕셔너리를 대입
add_numbers( **{"x" :6, "y":4})

# 리스트를 대입
add_numbers( *[3, 2])
add_numbers 함수가 호출되었습니다.
함수호출 결과 :  10
add_numbers 함수가 호출되었습니다.
함수호출 결과 :  5
In [21]:
# 인자가 3개이더라도, 초기값만 설정되어있다면, 2개만 넣어줘도 알아서 처리된다.
add_number(1, 2)
add_number 함수가 호출되었습니다.
함수호출 결과 :  3
In [ ]:
 

+ Recent posts