[Python] Arguments Syntax

rang-dev·2020년 5월 26일
0

Parameter vs Argument

하다보니 헷갈려 미칠거같아서 정리한다!(참고)

  • Parameter: 함수 정의에서 나열되는 변수명(Variable)
  • Argument: 함수 호출시 전달, 입력되는 실제 값(Value)
def love_you(my_name, your_name):
	print(f'{my_name} loves {your_name}')

이렇게 함수를 정의할때 함수에 사용한 변수인 my_name, your_nameparameter이고 이렇게 정의한 함수를 love_you("나", "너")로 호출하면 여기에 입력된 value인 , argument이다.

Arguments Syntax

  • Positional Arguments
def love_you(my_name, your_name):
	print(f'{my_name} loves {your_name}')
    
love_you("나", "너")

입력한 순서대로 값이 parameter로 함수에 전해지는 경우가 가장 기본이다.

  • Kewords Arguments
def love_you(my_name, your_name):
	print(f'{my_name} loves {your_name}')
    
love_you(your_name="너", my_name="나")

Keyword arguments 방식으로 parameter 값을 전해주면 parameter 순서가 바뀌어도 상관이 없고 가독성도 더 높아진다. 또한 실수로 값이 바뀔 확률이 더 적다.

  • Mixing positional arguments and keyword arguments

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

Assignment1

Error

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보다 뒤에 위치할 수 없다.

Solution

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가 2개 이상일때

위에서 알아본 것과 같이 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("나")
    • my_name=나, your_name=너, group_name=wecode
  • love_you("나", "YOU")
    • my_name=나 your_name=YOU, group_name=wecode가 된다. your_name은 내버려두고 group_name을 지정하고 싶다고해서 바로 love_you("나", "GROUP_NAME")을 할 수 없고 위치를 맞춰주어야한다.
    • 그 이유는 default arguments는 keyword arguments처럼 keyword로 직접 지정해 줄수 없으므로 positional한 성격을 가지고 있기 때문이다.

🤨 positional arguments와 keyword arguments가 헷갈려요

이렇게 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를 사용할지는 함수를 호출할때 결정한다.

  • Positional arguments를 사용했을 때
test("positional argument")
> non_default: positional argument, default1: 안녕, default2: wecode


test("positional argument", "순서", "중요해요")
> non_default: positional argument, default1: 순서, default2: 중요해요
  • Keyword arguments를 사용했을 때
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에서 다룬다.

Assignment2

Error

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'

Solution

여기서 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

Assignment3

Error

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

Solution

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

Assignment4

Error

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

Solution

일단 오류가 난 이유는 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들의 상태는 다음과 같다.

  • positonal arguments: 20, "012341234", "male"
  • keyword arguments: mobile, address

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들의 종류와 위치를 제대로 알고 있는 것이 중요하다.

참고: https://getkt.com/blog/python-keyword-only-arguments/

profile
지금 있는 곳에서, 내가 가진 것으로, 할 수 있는 일을 하기 🐢

0개의 댓글