본문 바로가기

Python

Python - Function Parameters

Parameters vs Arguments

함수 선언부에 있는 이름은 parameter,

함수를 호출하며 넣어서 함수에 전달된 값은 argument이다. 참고 링크

 

함수를 호출할 때는 함수 선언시 정해둔 규정에 따라 argument를 전달해야 된다. 어떤 값은 위치에 맞추어, 어떤 값은 keyword를 주며 넣어야 되는데 이는 함수 정의부의 Parameter 순서를 보고 구분할 수 있다.

기본적으로는 위치 인자 - 가변 인자(*args) - 키워드 가변 인자(*kwargs) 순이다.

여기에 default까지 추가하면,

위치 인자 - default 인자 - 가변 인자(*args) - 키워드(w/, w/o default 순서 상관 없음) - 키워드 가변 인자(**kwargs)

이게 최종! 이를 익힌 예제는 아래에 있다.

parameter에 값을 전해주는 방식

위치 인자(positional argument) - parameter 하나에 위치가 일치하는 argument 한 개 전달.

 

가변 인자(variable length argument) - tuple 취급. 대개 *args로 쓴다.

키워드 가변 인자(variable length keyword arguments) - dict 취급. 대개 *kwargs로 쓴다.

 

parameter default value - 함수 선언시 parameter과 함께 정의하는 값이다.


예제

1. 가변 인자 뒤에 위치 인자를 선언할 때

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가 모든 argument들을 가져가기 때문에 그 뒤에 age를 positional로 선언하면 age에 들어갈 값이 없다.

*args의 선언 위치를 맨 뒤로 옮기려면 함수 호출시 age 값을 준 위치를 순서와 일치하게 바꿔야 값이 맞게 들어간다. 또는 선언 위치는 그대로 두되 keyword 방식으로 하면 값 20을 parameter age에 전달할 수 있다. 후자의 방법으로 코드를 수정했다.

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

 

결과


2. 키워드 가변 인자 위치

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

에러

가변 인자 뒤에 다른 인자에 값을 넣는데 통하던 keyword 방식이 키워드 가변 인자에는 먹히지 않는다. 키워드 가변 인자는 무조건 맨 뒤에 선언해야 된다.

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)

**kwargs 선언 위치를 맨 뒤로 바꿨다. 함수 호출문은 변경하지 않았다.

결과


3. 종합

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

에러

만일 (name="아이유", age, address, *args, **kwargs) 이렇게 수정하면 다른 에러가 난다.

default argument 관련 에러

default argument의 위치가 문제니 이걸 옮겼다. (age, address, name="아이유", *args, **kwargs) 이렇게 수정하면 또 다른 에러가 난다.

keyword argument 관련 에러

default argument의 위치가 여기가 아닌가 싶어서 (age, name="아이유", address, *args, **kwargs) 이렇게 바꿨더니 다시 non-default가 default 뒤로 왔다고 에러 났다. 그럼 keyword argument로 준 address의 위치를 바꿔본다.

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

함수 호출문은 변경하지 않았다. (positional, *args, *kwargs) 이 순서만 지키면 될 줄 알았는데 default argument의 위치가 까다롭다. 호출문을 변경, age를 keyword argument로 바꿔 positional이 없게 하고 age의 위치를 *args 뒤로 옮겨 해결한 다른 사람의 방법도 있다.

결과


default argument를 non-default argument 앞에 정의하면 안되는 이유

default argument는 함수 선언시 이에 해당하는 param을 주지 않을 수 있다. 이런 경우 default argument가 보다 앞쪽에 선언된 형태에서는 positional argument에 들어가는 값에 변동이 생긴다. 파이썬에서는 이런 혼란을 syntax로 막아둔 것.

이 질문의 해답을 내가 생각해내고 싶어서 가장 나중에 손 댔다! 다 이해하고 나니 이 대답이 당연하게 나왔다.

cf. keyword argument 선언 순서는 default 값을 주었는지 여부와 상관 없다.

def mixed_params(age, name="아이유", *args, country="somewhere", 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", country="Korea")

위처럼 keyword-only argument with default가 앞에 오나 (age, name="아이유", *args, address, country="somewhere", **kwargs) 이런 형태로 뒤에 오나 둘 다 정상 출력된다.


keyword-only arguments with defaults 인지하기

keyword-only arguments with defaults라는 걸 참고 링크의 그림에서 처음 봤을 땐 이게 뭔 소리지 싶었다. keyword가 붙지 않은 default argument가 이미 val=num1 이런 형태인데 이것과 어떻게 구분하나 싶어서.

결론부터 얘기하자면 선언 위치로 구분한다. 가변 인자 뒤에 선언하면서 동시에 default 값이 같이 선언되어 있는 인자는 함수 호출시 반드시 keyword를 줘서 넣어야 된다.

 

Any argument after * must be specified using a keyword (참고 링크) 예제

def func_param_with_var_args(name="정우성", age=20):
    print("name=",end=""), print(name)
    print("age=",end=""), print(age)
    

func_param_with_var_args("정우성", 30)

위의 예제 코드는 정상이다. name과 age는 둘 다 default argument이다. 여기다 *를 껴넣어 아래와 같이 바꾸면 에러가 난다.

def func_param_with_var_args(name="정우성", *, age=20):
    print("name=",end=""), print(name)
    print("age=",end=""), print(age)
    

func_param_with_var_args("정우성", 30)

에러

함수 호출시 age를 keyword로 주면 해결된다.

func_param_with_var_args("정우성", age=30)

 

 

'Python' 카테고리의 다른 글

Python - Tuple  (0) 2021.01.15
Python - List  (0) 2021.01.14
Python - String Formatting  (0) 2021.01.14
Python - 변수와 기초 연산  (0) 2021.01.13
Python - 입력값 받기  (0) 2020.12.28