TIL-5. 파라미터 / 위치 인수와 가변 인수, 가변 키워드 인수

24373 단어 WeCodeTILTIL

1. default value parameter를

non-defalut value parameter 앞에 정의하면 안 되는 이유

함수를 정의할 때 파라미터에 디폴트 값을 정의해 줄 수가 있다.
해당 파라미터는 함수 호출 시 값을 따로 넘기지 않아도 자동으로
디폴트 값이 넘겨지게 된다.
이때 주의할 점은 디폴트로 정의된 파라미터가 디폴트로 정의되지 않은 파라미터 앞에 위치하면 안 된다.

이유는?

먼저 순서에 맞춰 파라미터 값을 전해 주는 positional arguments와
순서에 상관 없이 파라미터 값을 전해 주는 keyword arguments를 알아야 한다.

positional arguments는 1:1 매칭하듯 작성하는 방식인데
아래 예시를 보면 이해가 쉽다.

def data(my_name, my_age):
    print(f"{my_name} and {my_age}")

data("김코드", 30)

data에 인자로 김코드와 30을 넘겨줄 때
함수에서 설정한 순서대로 (my_name, my_age) 작성하는 방식이다.

반면에 keyword arguments는 이름에서 유추해 볼 수 있듯
인자에 키워드 자체를 심어서 함수에 전달한다.

def data(my_age, my_name):
    print(f"{my_name} and {my_age}")

data(my_name="김코드", my_age=30)

이런 식으로 자리를 맞추지 않아도 키워드 자체를 지정했기 때문에
알아서 자기 자리로 잘 찾아들어간다.

만약 이 둘을 혼용해 사용한다면 어떨까?
당연히 positional arguments는 지정된 자리 순서에 맞춰 인자를 전달해야 하므로
아무리 keyword arguments가 자유로운 영혼이라 한들
positional arguments를 기준으로 순서를 지켜줘야 한다.

다시 본론으로 돌아와서,
바로 이 positional arguments 때문에 default로 지정된 값은
가장 마지막 자리로 빠져야 하는 것이다.

def data(my_name="김코드", my_age, my_car):
    print(f"{my_name} and {my_age} and {my_car}")

data(30, my_car="BMW")

위 코드를 보면 my_name 파라미터는 첫 번째 자리에 "김코드"라는 디폴트 값으로 지정되어 있다.
하지만 함수 호출할 때 보면 my_age가 첫 번째 자리, my_car가 두 번째 자리에 지정돼 값을 넘겨주고 있는 걸 볼 수 있다.
즉, 자리가 맞지 않게 되는 오류로 인해 SyntaxError가 발생하게 되는 것이다.
만약 my_name="김코드"를 맨 뒷자리로 옮기면 자리 순서에 문제가 없으므로
정상적인 결과를 얻을 수 있게 된다.

2. 위치 인수(positional arguments)와 가변 인수(variable length arguments)의 위치를 자료를 통해 조사하고 에러를 고쳐 정상 출력되게 만들어보자.

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)

args, 즉 가변 인수는 함수 호출 시 인자를 가변적으로 넣어줄 수 있다.
그렇기 때문에 함수 선언 시 가변 인수를 가장 뒤쪽으로 지정하지 않으면
자리가 꼬이게 되어 오류가 나오게 된다.
아래와 같이
args 가변 인수와 age 위치 인수의 자리를 바꾸어주고
함수 호출 시에도 순서에 맞게 위치를 바꾸어주어야 한다.

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")

3. 가변 키워드 인수의 위치를 자료를 통해 조사하고 어떤 에러가 발생하는지 확인, 에러를 고쳐 정상 출력시켜보자.

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")

마찬가지로 *kwargs도 함수 선언 시 위치를 가장 뒤쪽으로 빼주어야 하며,
(
args보다 더 뒤, 항상 맨 뒤)
함수 호출 시에는 키워드가 지정돼 있으므로 굳이 위치를 이동시키지 않아도 된다.

4. 위치 인수와 가변 키워드 인수의 위치를 자료를 통해 조사하고 에러가 발생한다면 알맞게 고쳐보자.

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 func(positional, default, *args, keyword, *kwargs)

위 내용을 참고해서 순서를 변경해 보면 아래와 같다.

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" ,mobile="01012341234", address="seoul")

그런데 한 가지 궁금증이 생겼다.
두 번째 파라미터인 name="아이유"는 디폴트 값으로 지정이 되었는데,
이 경우 함수 호출 시 인자를 생략해도 된다고 배웠다.
그래서 "정우성" 값을 지우고 호출해 봤는데 name에 그 다음 위치의
번호값이 들어가버렸다.
원래라면 정우성부터 male까지 모두 *args 값으로 들어가야 하는 것이 아닌가?
이 궁금증을 슬랙으로 동기들에게 남겼고 답변을 기다리고 있다.


동기들에게 받은 답변 정리.
파라미터 위치가 중요하다.
파라미터에 디폴트 값을 지정할 땐 인자로 넘겨주는 값이 없어야 한다.

def func(age, name="김코드"):
..
..
func(20)

이런 식으로 인자에 age에 해당하는 값만 넣어주면
age = 20
name = "김코드" 라는 출력값을 얻을 수 있다.
하지만 위의 문제처럼 디폴트 값 뒤쪽으로 *agrs 파라미터가 있고
인자로 지정된 값들이 있을 땐 디폴트로서 작동할 수가 없다.
왜냐하면 인자에 값이 지정돼 버렸기 때문이다.
그렇기 때문에 아래의 이 순서대로 파라미터를 적어줘야 할 것이다.

def func(positional, *args, default, keyword, *kwargs)

def mixed_params(age, *args, name="아이유", 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" ,mobile="01012341234", address="seoul")

좋은 웹페이지 즐겨찾기