정의

함수에 Parameter가 여러개일 경우 함수 argument로 *args를 사용하면 여러개인 Parameter를 대응할 수 있다.
naming은 임의로 *dog, *cat 으로 지을수도 있지만, 관례적으로 *args를 쓰는 편이다.

설명

def test(*args):
    print(args)


>>> num_list = [1, 2, 3]
>>> print( test(*num_list) == test(1, 2, 3))
(1, 2, 3)
(1, 2, 3)
True

궁금중을 정리해보자

  1. test(*num_list) == test(1, 2, 3)가 어떻게 True를 반환하는 것인가?
  2. num_list를 그냥 넘기는게 아니라 왜 *num_list라고 앞에 *를 붙였나?

그럼 이 2가지 궁금증을 한꺼번에 풀 수 있는 예제를 들어보고자 한다.

일단 test2라는 함수를 만들고 그 함수의 Argument로 a, b, c를 받고 출력하는 간단한 함수를 만들어보면 아래와 같다.

def test2(a, b, c):
    print(a, b, c)

이 test2라는 함수를 사용하기 위해서는 test2(1, 2, 3)와 같이 사용할 수 있다.

여기까지는 다른 웬만한 프로그래밍 언어랑 별반 차이가 없어 보인다.


하지만 여기서 Python의 Magic을 부려보자.

그 매직이란게 어떤거냐면 위에서 선언한 num_list라는 Parameter를 하나만 전달해서 에러없이 test2를 호출하는 것이다.


어떻게 이게 가능할까?


파이썬에서 Packing, UnPacking이라는 개념을 사용하면 된다.

차근차근 살펴보자

num_list을 가지고 test2를 호출할려고 하면 일단 아래와 같이 호출 할 수 있다.

>>> num_list = [1, 2, 3]

>>> test2(num_list[0], num_list[1], num_list[2])
print(1, 2, 3)

위와 같이 호출하면 문제없이 호출이 될 것이다.

하지만 위의 예제코드는 pythonic하지 않다.

pythonic하게 Refactoring를 해보면 아래와 같다.

>>> test2(*num_list)
print(1, 2, 3)

위와같이 호출하니깐 문제없이 잘 될것이다.

앞에 *가 붙는게 맨 처음을 test함수를 호출할때랑 같다.


이 과정을 설명해보자면

test2(*num_list)로 호출하면 num_list가 unpacking되어서 a=1, b=2, c=3으로 전달되어서 에러 없이 잘 실행되는 것이다.

그럼 *를 앞에 안붙이고 그냥 test2(num_list)를 하면 어떻게 될까?

>>> test2(num_list)
TypeError: test2() missing 2 required positional arguments: 'b' and 'c'

당연한 이야기 지만 2개의 필수 Arguments를 전달 안했다고 에러가 난다.

인제 함수를 호출할때 왜 *num_list라고 쓰는지 이해가 될 것이다.

그럼 인제 맨처음에 생겼던 궁금증을 정리해보자



test(*num_list) == test(1, 2, 3)가 어떻게 True를 반환하는 것인가?

  • test(*num_list라고 호출할때 *num_list로 인해 unpacking이 되어서 전달
  • *args로 인해 다시 packing되어서 출력되기 때문에 둘다 출력결과가 같으므로 True

num_list를 그냥 넘기는게 아니라 왜 *num_list라고 앞에 *를 붙였나?

  • unpacking해서 넘길려고


결론적으로 호출할때 unpacking 실행될때 packing이라고 보면 된다.

블로그 이미지

LeoHeo

어제보다 더 나은 개발자가 되고자 합니다. LeoHeo - 허진한

,