하다보니 헷갈려 미칠거같아서 정리한다!(참고)
- Parameter: 함수 정의에서 나열되는 변수명(Variable)
- Argument: 함수 호출시 전달, 입력되는 실제 값(Value)
def love_you(my_name, your_name):
print(f'{my_name} loves {your_name}')
이렇게 함수를 정의할때 함수에 사용한 변수인 my_name
, your_name
은 parameter이고 이렇게 정의한 함수를 love_you("나", "너")
로 호출하면 여기에 입력된 value인 나
, 너
는 argument이다.
def love_you(my_name, your_name):
print(f'{my_name} loves {your_name}')
love_you("나", "너")
입력한 순서대로 값이 parameter로 함수에 전해지는 경우가 가장 기본이다.
def love_you(my_name, your_name):
print(f'{my_name} loves {your_name}')
love_you(your_name="너", my_name="나")
Keyword arguments 방식으로 parameter 값을 전해주면 parameter 순서가 바뀌어도 상관이 없고 가독성도 더 높아진다. 또한 실수로 값이 바뀔 확률이 더 적다.
positional arguments와 keyword arguments를 혼용하여 사용할수도 있다.
def love_you(my_name, your_name):
print(f'{my_name} loves {your_name}')
love_you("나", your_name="너")
주의할 점은 keyword arguments 는 순서가 바뀌어도 상관 없지만 positional arguments 부분은 순서를 지켜야 한다는 것이다.
def love_you(my_name, your_name, group_name):
print(f'{my_name} loves {your_name} and we are in {group_name}')
love_you("나", group_name="wecode", your_name="너")
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("나")
로 함수를 입력한다면 my_name
의 value를 바꾸라는건지 다른 파라메터(your_name
)의 값을 지정하라는건지 알 수가 없다.
--> 인터프리터에서 regular positional arguments를 먼저 처리하고 그 다음에 default arguments를 처리하기 때문에 default value parameter는 non-default value parameter보다 뒤에 위치할 수 없다.
def love_you(my_name, your_name="너"):
print(f"{my_name} loves {your_name}")
love_you("나")
이렇게 함수를 호출하면 전달인자와 파라메터 위치를 확인하여 positional argument인 나
는 my_name
으로 할당되고 그 다음에 default argument가 처리된다.
위에서 알아본 것과 같이 default value parameter는 non-default parameter 뒤에 위치해야한다.
def love_you(my_name, your_name="너", group_name="wecode"):
print(f"{my_name} loves {your_name} and we are in {group_name}")
만약 default value parameter가 여러개 있다면 함수에 주어지는 argument 순서대로 파라메터에 값이 할당된다.
love_you("나")
love_you("나", "YOU")
your_name
은 내버려두고 group_name
을 지정하고 싶다고해서 바로 love_you("나", "GROUP_NAME")
을 할 수 없고 위치를 맞춰주어야한다.이렇게 default와 non-default value parameter를 섞은 함수를 다루고보니 positional arguments와 keyword arguments가 혼동이 되기시작했다. 왜나면 둘다 default, non-default를 설정할 수 있기 때문이다.
이건 argument와 parameter를 혼동하기때문에 벌어진 일이다. default, non-default value는 parameter에서 설정해주는 것이고, positional을 사용할지 keyword arguments를 사용할지는 argument에서 정하는 것이다.
def test(non_default_param, default1="안녕", default2="wecode"):
print(f"non_default: {non_default_param}, default1: {default1}, default2: {default2}")
위의 함수에서 non-default, dafulat 파라메터를 각각 지정해 주었다. positional argument를 사용할지 keyword arguments를 사용할지는 함수를 호출할때 결정한다.
test("positional argument")
> non_default: positional argument, default1: 안녕, default2: wecode
test("positional argument", "순서", "중요해요")
> non_default: positional argument, default1: 순서, default2: 중요해요
test(non_default_param="keyword")
> non_default: keyword, default1: 안녕, default2: wecode
test(non_default_param="keyword", default2="안중요해요", default1="순서")
> non_default: keyword, default1: 순서, default2: 안중요해요
여기서 arguments의 종류가 더 다양해지면 더 복잡해지는데 이것은 이어지는 assignments에서 다룬다.
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("wecode", "01012341234", "seoul", 20)
Traceback (most recent call last):
File "main.py", line 60, in <module>
func_param_with_var_args("wecode", "01012341234", "seoul", 20)
TypeError: func_param_with_var_args() missing 1 required keyword-only argument: 'age'
여기서 positional arguments는 name
이고 variable length arguments는 *args
이다. 그리고 위치상 age
는 keyword arguments가 되어야한다.
우리가 보기에는 20이 age를 의미한다는 것을 유추할 수 있지만 인터프리터는 그렇지 않다. 인터프리터가 이해할 수 있도록 age를 keyword arguments로 전달했어야했는데 그렇지 않았기 때문에 오류가 발생했다. 그러므로 keyword인 age를 이용해서 age=20
으로 전달해야만 제대로 작동하게 될 것이다.
func_param_with_var_args("wecode", "01012341234", "seoul", age=20)
>name=wecode
args=('01012341234', 'seoul')
age=20
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("wecode", "20", mobile="01012341234", address="seoul")
> File "main.py", line 54
def func_param_with_kwargs(name, age, **kwargs, address=0):
^
SyntaxError: invalid syntax
variable length keyword argument(**kwrgs
)는 항상 맨 뒤에 위치해있어야한다. 하지만 keyword-only argument가 맨 뒤에 위치해있으므로 오류가 발생했다. positional/keyword-only/variable length keyword argument순이 될 수 있도록 파라메터를 수정해야한다.
def func_param_with_kwargs(name, age, address=0, **kwargs):
...
func_param_with_kwargs("wecode", "20", address="seoul", mobile="01012341234")
>name=wecode
age=20
kwargs={'mobile': '01012341234'}
address=seoul
def mixed_params(name="wecode", *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, "wecode", "01012341234", "male" ,mobile="01012341234", address="seoul")
> File "main.py", line 54
def mixed_params(name="wecode", *args, age, **kwargs, address):
^
SyntaxError: invalid syntax
일단 오류가 난 이유는 keyword arguments인 address
가 맨 마지막에 와야하는 vaiable length keyword argument 뒤에 왔기 때문이다.
그럼 **kwargs
만 맨 뒤로 이동하면 제대로 작동할지 확인해보자.
def mixed_params(name="wecode", *args, age, address, **kwargs):
...
mixed_params(20, "wecode", "01012341234", "male" ,mobile="01012341234", address="seoul")
> Traceback (most recent call last):
File "main.py", line 62, in <module>
mixed_params(20, "wecode", "01012341234", "male" ,mobile="01012341234", address="seoul")
TypeError: mixed_params() missing 1 required keyword-only argument: 'age'
keyword-only argument인 age
가 누락되었다는 오류가 나타났다. 그 이유는 keyword(age
)로 value를 지정해주지 않았기 때문이다.
현재 argument들의 상태는 다음과 같다.
mixed_params()
에서는 name
, *args
가 positional이고 age
, address
, **kwargs
가 keyword parameter이다.
positonal은 순서대로 적용되므로 나타난대로 적용해보면
name
= 20**args
= ("wecode", "01012341234", "male")처럼 나타날것이고 keyword arguments들은
mobile
= 01012341234**kwargs
= {address="seoul"}이 될 것이다. 예상대로 분류되는지 확인하기 위하여 임의적으로 age
를 다음과 같이 추가했다.
mixed_params(20, "wecode", "01012341234", "male" , age=30, mobile="01012341234", address="seoul")
> name=20
args=('wecode', '01012341234', 'male')
age=30
kwargs={'mobile': '01012341234'}
address=seoul
keyword argument로 추가해준 age
를 무시하고 생각한다면 예상한대로 값들이 할당된 것을 확인할 수 있다. 따라서 본래의 의도대로 name
이 wecode가 되고, age
가 20이 되기 위해서는 arguments의 위치를 다음과 같이 조정해주어야한다.
mixed_params("wecode", "01012341234", "male" , age=20, mobile="01012341234", address="seoul")
> name=wecode
args=('01012341234', 'male')
age=20
kwargs={'mobile': '01012341234'}
address=seoul
사실 이 예제에서는 name
에 어떤 값이 와야하는지, age
는 얼마나 되야하는지 보고 임의로 판단할 수 있었지만 만약 함수가 더 복잡해진다면 나중에는 어떤 값들을 수정해야할지 알아내기 매우 힘들어진다. 그렇기때문에 함수를 다룰때 arguments들의 종류와 위치를 제대로 알고 있는 것이 중요하다.