먼저 default value paramter와 non-default value parameter에 대해서 알아보자.
def dinner(food, dessert):
print( f"{food}를(을) 먼저 먹고, {dessert}를(을) 나중에 먹는다.")
dinner("고기", "커피")
>>"고기를(을) 먼저 먹고, 커피를(을) 나중에 먹는다."
non-default value parameter 일때는 위와 같이 인수 값을 주었을 때 인자값에 맞춰 output이 출력된다.
def dinner(food, dessert="크로플"):
print( f"{food}를(을) 먼저 먹고, {dessert}를(을) 나중에 먹는다.")
dinner("고기")
>>"고기를(을) 먼저 먹고, 크로플를(을) 나중에 먹는다."
default value parameter가 일때는 함수에 대한 인자값으로 "고기"만 주어도 default parameter로 "크로플"이 있기 때문에 위와 같이 output이 출력된다.
이제 위 질문에 대해서 생각해보자. default value parameter가 non-default value parameter 먼저 정의된다면 어떻게 될것인가?
def dinner(food="고기", dessert):
print( f"{food}를(을) 먼저 먹고, {dessert}를(을) 나중에 먹는다.")
dinner("크로플")
>>error
위와 같이 에러가 발생한다. 그 이유는 default parameter가 앞에 있으면 인자가 하나가 들어올 때 그것이 food에 대한 인자인지, dessert에 대한 인자인지 알 수 없기 때문이다. 그렇기 때문에 default parameter를 정의할 때에는 항상 마지막에 정의해야 한다.
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)
>> TypeError: func_param_with_var_args() missing 1 required keyword-only argument: 'age'
위와 같이 코드를 작성하였을 때 'age' 값에 대한 인수가 없다고 하면서 에러가 발생한다.
그 이유는 *args는 가변 인수로 인수가 얼마나 들어오는 지 알 수 없을 경우에 사용된다.
그러므로 인수인("정우성", "01012341234", "seoul", 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("정우성", "01012341234", "seoul", 20)
>>
name=정우성
args=('seoul', 20)
age=01012341234
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")
>> 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", address="seoul", mobile="01012341234")
>>
name=정우성
age=20
kwargs={'mobile': '01012341234'}
address=seoul
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")
>> SyntaxError: invalid syntax
위 함수는 다양한 형태의 파라미터를 통해서 다양한 인수값들 받고 있다.
(name="아이유", *args, age, **kwargs, address)
default 인수, 가변인수, 일반인수, 키워드 가변인수, 일반인수 순으로 되어 있다.
그러면 어떤 순서대로 인수를 정의하여야 오류가 발생하지 않고 코드가 실행할 수 있을지 알아보자.
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, address="seoul", "정우성", "01012341234", "male", mobile="01012341234",)
>> SyntaxError: positional argument follows keyword argument
이전의 invalid Syntax와는 다른 에러가 발생한다. "SyntaxError: positional argument follows keyword argument". 잘못된 파라미터 순서에 따른 오류가 발생하였다.
여기서 생각해보니 일반인수를 받는 address에 address="seoul"로 인수가 정의되어 있었다. 이를 받기 위해서는 키워드 가변 인수로 정의되어 있어야 하는 것이 아닌가 싶었다. 그러나 알고보니 형식은 같지만 이후 함수로 받을 때 dict 형태가 아닌 일반인수가 받는 형태로 output 만들어지는 Keyword-Only-Argument였다.
인터넷을 찾아보니 Keyword-Only-Argument는 가변 위치 인수 뒤에 위치해야 한다고 한다. 오류를 기반으로 인수 간 우선순위를 생각해 보았다.
이를 바탕으로 다시 한 번 코드를 짜서 돌려보았다.
def mixed_params(age, name="아이유", *args, address, **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, "정우성", "01012341234", "male", address="seoul", mobile="01012341234")
>>
name=정우성
args=('01012341234', 'male')
age=20
kwargs={'mobile': '01012341234'}
address=seoul
에러 없이 잘 작동되었다.
함수 파라미터를 정의할 때 꼭 파라미터와 인수의 우선순위를 생각하여 정의하도록 하자.