함수는 복잡한 코드를 하나의 모듈로 만들어 가독성과 유지보수성을 향상시키는데 도움을 줍니다.
Python의 함수는 다른 언어와 마찬가지로 매개변수 즉 parameter를 인자로 받아와 함수 내부에서 변수로 사용할 수 있습니다.

하지만 함수에서 사용되는 인자의 값이 3개가 아니라 30개 300개 3천개라면 어떨까요?

함수를 정의하는 부분에서 이미 굉장히 긴 코드라인을 형성할 것입니다.

이런 문제는 오늘 포스팅에서 알아볼 *args**kwargs를 통해 해결할 수 있겠습니다!

  1. 함수의 인자 사용 방법
  2. *args
  3. **kwargs

📌 함수의 인자


우리는 함수를 통해 지정된 변수가 아니라 사용자의 다양한 요청 값을 변수로 불러와 매번 다른 값을 반환할 수 있습니다.

다음과 같이 할 수 있습니다.

def add(a, b, c) :
return a + b + c

add(1, 2, 3) # result: 6

add라는 함수의 인자로 1, 2, 3을 넣어주었습니다.
이 인자는 함수 정의 부분에서 파라미터 순서와 동일하게 적용되어 각각 a=1, b=2, c=3 값이 대입됩니다.

여기서 마지막 줄의 코드를 다음과 같이 바꾸면

add(3, 1, 2) #result: 6

인자의 순서만 바꾸었으니 결과값은 동일합니다.
하지만 각 parameter에 대입되는 값은 각각 a=3, b=1, c=2로 바뀌게 됩니다.

즉, 함수를 정의할 때 parameter를 작성한 순서에 따라, 함수를 호출할 때 인자의 값이 순서대로 대입된다는 것을 의미합니다.


📌 *args (가변인수)


변수이름 (hamburgers)

변수이름이 꼭 args일 필요는 없습니다.

다양한 변수가 동일한 유형이라면 그 유형을 변수 명으로 선언해도 좋습니다.

더욱 고도화된 기술을 구현하기 위해 우리는 함수의 매개변수를 3가지 이상 사용하는 경우도 있을 것입니다.

그 개수가 30, 300, 3억개가 된다면 우리는 함수를 어떻게 다뤄야할까요?

바로 *변수이름 표현식을 사용할 수 있습니다.

우선, 함수를 정의할 때 매개변수로 *args를 작성해줍니다.

함수를 호출할 때 불러오는 인자의 개수는 상관이 없습니다.

하지만 순서는 중요합니다.

코드를 통해 알아보겠습니다.

def smart_phone_type(maker, *smartphones ) :
	print(maker, smartphones)

smart_phone_type("apple", "아이폰3", "아이폰4", "아이폰5", "아이폰6")

결과는 다음과 같습니다.

"apple" ("아이폰3", "아이폰4", "아이폰5, "아이폰6")

maker 매개변수의 위치의 apple은 문자열 그대로 출력됩니다.
*smartphones 매개변수의 위치는 "apple" 이후의 인자를 모두 받아 튜플이라는 데이터 타입으로 출력됩니다.

함수 정의 부분에서 매개변수의 순서를 바꿔보겠습니다.

def smart_phone_type(*smartphones, maker) :
	print(smartphones, maker)

smart_phone_type("아이폰3", "아이폰4", "아이폰5", "아이폰6", "apple")

결과는 다음과 같습니다.

TypeError: smart_phone_type() missing 1 required keyword-only argument: 'maker'

maker에 해당하는 인자를 찾지 못했다네요!

*args는 인자의 시작과 끝부분을 지정할 수 없습니다.

따라서 다른 매개변수명과 같이 사용한다면, 매개변수명을 우선적으로 선언해줘야 원하는 결과를 얻을 수 있을 것입니다.


📌 *kwargs (가변 키워드 인수)


변수이름 (hamburgers)

keyword arguments의 약자입니다.

key라는 말이 들어있네요, 일단 의심부터 해봅니다.

그렇습니다.

key = "vlaue"의 형태로 인자를 함수의 매개변수에 대입할 수 있습니다.

코드를 통해 알아보겠습니다.

def smart_phones(**smartphones) :
	print(smartphones)
    
smart_phones(애플="아이폰14", 삼성="갤럭시21")

결과는 다음과 같습니다!

{'애플': '아이폰14', '삼성': '갤럭시21'}

오 이번엔 딕셔너리 형태로 출력이 되었네요!


📌 예제 코드 (과제)


default value parametenon-default-value-parameter보다 나중에 정의해야 합니다.
그 이유는 함수 호출 단계에서 인자를 순서대로 할당되지 않기 때문입니다.

  • default value란?
def 함수(첫번째="기본값_1") :
	return 첫번째

위 코드와 같이 매개변수의 초기값을 설정해주는 것을 의미합니다.

그렇다면 왜 초기값이 설정된 매개변수를 그렇지 않은 매개변수보다 나중에 정의해야 할까요?

다음의 코드를 실행시켜보겠습니다.
두번째 매개변수는 값이 2로 초기값이 설정되어 있네요!

def number(first, second = 2, third) :
	print(f"""{first}, {second}, {third}""")

number(1,3)

결과는 다음과 같습니다.

SyntaxError: non-default-argument follows default argument

number함수의 인자로 1과 3은 firstsecond에 할당되고, third에는 할당되지 않습니다. 인수의 두번째 값으로 받은 3이 second 매개변수의 값을 변경하는 것인지, third 매개변수에 할당하는 것인지 알 수 없기 때문입니다.


가변 인수는 위치 인수보다 나중에 정의되어야 합니다.
가변 인수의 범위를 지정하여 인자를 매개변수의 값으로 할당할 수 없기 때문입니다.

다음 코드는 마지막 줄과 같은 에러가 발생하는 코드입니다

def func_param_with_var_args(name, *args, age):
    print("name=",end=""), print(name)
    print("args=",end=""), print(args)
    print("age=",end=""), print(age)

func_param_with_var_args("정우성", "01012341234", "seoul", 20)

# result
# TypeError: func_param_with_var_args() missing 1 required keyword-only argument: "age"

가변 인수 *args의 범위는 위치 인수가 끝나는 지점부터 마지막 인수라고 이해하면 좋겠습니다.
그렇기 때문에 age에 할당되는 인수가 없다는 에러가 발생했습니다.

다음과 같이 코드를 수정해볼 수 있겠네요
함수의 파라미터로 정의된 age*args의 위치를 바꾸어 줍니다.
호출을 할 때도 위치 인자의 순서에 맞게 20이라는 값을 두번째 위치로 옮겨주었습니다.

def func_param_with_var_args(name, age, *args):
    print("name=",end=""), print(name)
    print("args=",end=""), print(args)
    print("age=",end=""), print(age)

func_param_with_var_args("정우성", 20, "01012341234", "seoul")

결과는 다음과 같습니다.

name="정우성"
args=("01012341234", "seoul")
age=20

가변 키워드 인수는 위치 인수, default-value-parameter 보다 나중에 정의되어야 합니다.
가변 인수의 범위를 지정하여 인자를 매개변수의 값으로 할당할 수 없기 때문입니다.

앞서 말했든 초기값이 설정된 인수는 위치 인수보다 늦게 정의되어야 합니다.

가변 키워드 인수 역시 선행되어 작성하면 코드에 에러가 있다는 것을 알 수 있을 것입니다.

순서는 다음과 같습니다.

위치인수1, defualt-value, **krags

코드를 통해 알아보겠습니다.

def func_param_with_kwargs(name, age, **kwargs, address=0):
    print("name=",end=""), print(name)
    print("age=",end=""), print(age)
    print("kwargs=",end=""), print(kwargs)
    print("address=",end=""), print(address)

func_param_with_kwargs("정우성", "20", mobile="01012341234", address="seoul")

# result
# SyntaxError: invalid syntax

올바르지 않은 구문이라는 메시지를 확인할 수 있습니다.

코드를 수정해보겠습니다.
가변 키워드 인자의 위치를 가장 마지막으로 수정해주었습니다.

def func_param_with_kwargs(name, age, address=0, **kwargs,):
    print("name=",end=""), print(name)
    print("age=",end=""), print(age)
    print("kwargs=",end=""), print(kwargs)
    print("address=",end=""), print(address)

func_param_with_kwargs("정우성", "20", mobile="01012341234", address="seoul")

결과는 다음과 같습니다.
address는 초기값을 설정해주었기 때문에 함수를 호출할 때 address라는 매개변수를 다시 언급해준다면 순서에 구애받지 않고 값이 할당됩니다.

name="정우성"
age=20
kwargs={"mobile" : "01012341234"}
address="seoul"

결론: 위치인수, default-value, *args, **kwargs 순서로 매개변수를 정의해주어야 합니다.

마지막으로 코드를 통해 알아보겠습니다.

아래의 코드 역시 syntax error를 출력하는 코드입니다.

def mixed_params(name="아이유", *args, age, **kwargs, address):
    print("name=",end=""), print(name)
    print("args=",end=""), print(args)
    print("age=",end=""), print(age)
    print("kwargs=",end=""), print(kwargs)
    print("address=",end=""), print(address)

mixed_params(20, "정우성", "01012341234", "male" ,mobile="01012341234", address="seoul")

코드를 수정해볼까요?
우선 함수 정의 부분에서 매개변수의 순서를 바꾸어줍니다.
이후 매개변수의 위치인자 순서에 맞게 함수 호출 부분에서 인자의 순서를 바꾸어줍니다.

def mixed_params(age, address, name="아이유", *args, **kwargs):
    print("name=",end=""), print(name)
    print("args=",end=""), print(args)
    print("age=",end=""), print(age)
    print("kwargs=",end=""), print(kwargs)
    print("address=",end=""), print(address)

mixed_params(20, "seoul", "정우성", "01012341234", "male" ,mobile="01012341234")

결과는 다음과 같습니다.

name="정우성"
args=("01012341234, "male")
age=20
kwargs={"mobile": "01012341234"}
address="seoul"

[참고자료]
WECODE 부트캠프 레플릿 자료
https://www.w3schools.com/python/python_functions.asp
https://wikidocs.net/24

profile
누구나 이해할 수 있도록

0개의 댓글