Python에서 함수는 parameter를 받아서 return값으로 output을 한다.
예를 들어,
def profile(name, age): print(f"name: {name}, age: {age}") profile("James", 21)
여기서
def profile()
안에name
,age
가 parameters,
아래profile()
안의"James"
,21
이 arguments 이다.
arguments들을 받아서 그 parameter로 함수에 적용하는 것이다.
위처럼 순서대로 parameter를 적용하거나,
아니면 keyword arguments(kwargs)를 이용하여 parameter를 지정할 수 있다.
(이때는 순서를 상관하지 않아도 된다.)
그러나 둘을 섞어쓸때에는 반드시 positional arguments가 keyword arguments보다 먼저 사용되어야 한다.
ex)
def profile(name, age): print(f"name: {name}, age: {age}") profile(name = "James", 21)
error 발생, 순서를 바꾸면?
def profile(name, age): print(f"name: {name}, age: {age}") profile(21, name = "James")
Traceback (most recent call last): File "/Users/choemin/Desktop/Project/peplit 1.py", line 3, in <module> profile(21, name = "James") TypeError: profile() got multiple values for argument 'name'
name
이 두번 지정되었다는 error 발생,def profile(name, age): print(f"name: {name}, age: {age}") profile("James", age = 21)
name: James, age: 21
위와 같은 방법으로 사용하여야 한다.
또, parameter에 default value를 지정하여 해당하는 값을 받지 않아도 함수를 실행할 수 있다.
하지만 default value parameter를 non-default value parameter 앞에 정의하면 안된다.
이러한 순서는 python에서 왜 중요한 것일까?
위 그림을 보면 parameter의 순서를 한 눈에 알아볼 수 있다.
- 먼저 보통의 positional arguments들을 받는 parameter가 제일 앞에오고,
- 그 다음으로 default value를 갖지만 positional arguments를 받는 parameter,
- 세번째로 variable length positional arguments(가변 인수,*args)의 parameter,
- 다음으로는 keyword arguments를 받는 parameter들 중, non-default value 그리고 default value 순서로,
- 마지막으로는 variable length keyword arguments(가변 키워드 인수,**kwargs)가 온다.
그렇다면 default value parameter가 non-default 뒤에 정의해야하는 이유는 무엇일까?
python에서는 함수를 정의하거나 호출할 때 인수가 정확하게 호출 될 수 있는지에 평가를 하고 결정한다.
그래서 매개변수들 중에서 먼저 positional arguments들을 순서대로 할당하고, keyword arguments를 나중에 할당하게 된다.
위에서 보았던 ex)에서 에러가 발생한 이유도,
def profile(name, age): print(f"name: {name}, age: {age}") profile(name = "James", 21)
positional argument
21
이 먼저name
에 할당되고 남은 keyword argument가 중복해서 할당되고,age
의 값을 지정할 수 없기 때문에 생기는 것이다.
그럼 예제를 살펴보면,
def love_you(my_name = "정우성", your_name): print(f"{my_name} loves {your_name}")
Traceback (most recent call last): File "python", line 1 SyntaxError: non-default argument follows default argument
여기서
love_you("아이유","이정재")
함수를 사용했다고 가정 했을때,
아이유
라는 인수가 어떠한 parameter를 지정해는지 알 수 없기 때문에 이를 명시적으로 할당해 주어야 한다.
이 문제를 해결하기 위해서는 둘의 순서를 바꾸면 해결이 가능하다.def love_you(your_name, my_name = "정우성"): print(f"{my_name} loves {your_name}") love_you("아이유", "이정재")
이정재 loves 아이유
가변 인수(aka. *args)는 arguments들 중 parmeter가 지정되지 않은 positional 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)
name
-"정우성"
순서대로 지정되고,
나머지"01012341234"
,"seoul"
,20
이 모두 positional argument이기 때문에 다 불러와서age
에 할당할 값이 사라지게 된다.
solution
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, "seoul", "01012341234")
*args
를 맨 뒤로 보내고,age
에 맞는20
값을 2번째에 둔다.
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", age = 20)
age
에 해당하는 인수를 keyword arguments로 만들어준다.
가변 키워드 인수(aka, **kwargs)는 지정되지 않은 모든 keyword arguments를 불러온다. 즉, (a = b)를 딕셔너리 형태 {a : b}로 함수에게 전달한다.
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
는 항상 parameter의 마지막에 위치해야 한다!
solution
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")
마지막으로는 *args와 **kwargs가 섞여있는 문제이다.
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")
solution
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 arguments를 할당받는
age
를 맨 앞으로 수정하고,
**kwargs
를 맨 뒤로 수정하였다.
참조
(https://getkt.com/blog/python-keyword-only-arguments/)
(https://brunch.co.kr/@princox/180)