함수 정의 시 default value parameter와 non-default value parameter

yo·2020년 5월 26일
0

목차
1. positional arguments
2. keyword arguments
3. positional arguments + keyword arguments
4. default value
5. 함수 정의 시 default value parameter를 non-default value parameter 앞에 정의하면 안되는 이유에 대한 추측
6. 추가과제들

참고
parameter-매개변수 (함수 선언 시의 이름)
arguments-인자, 인수(함수 호출 시 이름)

1.positional arguments

복수의 parameter 를 사용하는 가장 기본적 함수 정의 형태는 아래와 같다.
함수 호출 시 parameter의 순서대로 선언하는 것이 원칙이다.
컴퓨터가 앞에서부터 순서대로 할당하기 때문이다. 순서가 중요하다.

2. keyword arguments

예외적으로 함수 호출 시 순서를 지키지 않아도 되는 방법이 있다.
아래와 같이 keyword arguments를 사용하는 것이다.
이렇게 하면 컴퓨터는 해당 키워드에 맞게 알아서 해석한다.

3. positional arguments + keyword arguments

위의 연장선으로 positional arguments와 keyword arguments를 같이 사용할 수 있다.

중요한 것은 potisional이 keword 앞에 나와야 한다!

def love_you(my_name, your_name):
  print(f"{my_name} loves {your_name}" )

위의 함수를 positional arguments+keyword arguments방식을 사용해 가능한 모든 경우의 수로 호출을 해보자.

1)love_you("A", your_name="B" )
2)love_you(my_name="A", "B" )
3)love_you(your_name="B", "A" )

결과:
1)만 작동하고 2)와 3)은 에러가 발생한다.
'SyntaxError: positional argument follows keyword argument'

4. default value

default value는 함수 호출 시 parameter를 적지 않아도 기본값을 부여한다.
기본 예시는 아래와 같다.

가장 중요한 건 함수 선언 시 default value parameter가 non-default value parameter의 앞에 오면 안된다.
아래처럼 non-default value parameter가 default value parameter의 뒤에 나올 경우 오류가 발생한다.

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

5. 함수 정의 시 default value parameter를 non-default value parameter 앞에 정의하면 안되는 이유에 대한 추측

아래 코드는 디폴트 인자가 뒤에 온 예시로 문제 없이 실행된다.

def func(a, b, c="3" , d="4"):
  print(f"{a} {b} {c} {d}" )

func(1, 2)

이번엔 default value parameter가 non-default value parameter의 앞에 올 수 있다고 가정해보자.

def func(a='1', b='2', c, d):
  print(f"{a} {b} {c} {d}" )

func(1, 2)

호출된 함수의 (1, 2) 어느 요소에 할당 할 것인지 컴퓨터가 해석할 수가 없다.

아래의 예시는 더욱 더 혼란스럽다.

def func(a='1', b='2', c, d, e='5'):
  print(f"{a} {b} {c} {d} {e}" )

func(3, 4, 5)

3,4,5 는 어디에 할당되어야 하는가?
c,d,e인가? ->순서대로 할당되어야 하는 법칙에 위배된다.
a,b,c인가? ->d가 값을 가지지 못하게 된다.
어찌해야 할지를 모르겠다. 컴퓨터도 그럴 것이다.

결론
파이썬은 기본적으로 순서대로 parameter들을 match하게 프로그램 되어있다.
default value parameter가 앞에 나와버리면 컴퓨터가 해석할 수 없는 방법이 되고 많은 오류가 발생할 것이다.
default value parameter를 non-default value parameter 앞에 정의 하지 말아야만 하는 이유라 생각한다.

------------------------추가과제----------------------------------

위 코드 실행시 아래의 에러가 발생한다.

Traceback (most recent call last):
  File "python", line 7, in <module>
TypeError: func_param_with_var_args() missing 1 required keyword-only argument: 'age'

어떤 에러인지 알고 이를 해결하기 위해 args를 알아보자. (args는 non-keyworded arguments)
args는 arguments의 약자다. 함수 인수를 여러개 받을 때, 몇개의 인수가 들어올지 모를 때 사용한다. 즉, 복수의 인수를 받을 수 있는 것이다.
이름이 꼭 args일 필요는 없다. *tomato여도 된다. 다만 애스터리스크를 사용시 복수의 인수를 받게 된다는 것만 알면 된다. 간단한 예시를 살펴보자.

def func(a, b, *tomato):
  print(a)
  print(b)
  print(tomato)

func(1,2,3,4,5,6,7,8,9)

결과
1
2
(3, 4, 5, 6, 7, 8, 9)

이제 문제로 주어진 코드에서 왜 오류가 발생했는지 알 수 있다.
"wecode", "01012341234", "seoul", 20이 입력됐다.
먼저 name에 "wecode가 할당된다. 그 뒤 *args가 나머지 인수들을 모두 흡수하고, 불쌍한 age는 아무것도 할당받지 못하여 오류가 발생한다.
여하튼 *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("wecode", "01012341234", "seoul", 20)

결과
name=wecode
args=('seoul', 20)
age=01012341234

  1. 위 문제를 해결하기 위해 먼저 **kwargs를 알아야 한다.
    별표가 두개 붙은 keyworded arugments는 전달 받은 인수를 함수 내에서 dictionary처럼 다룰 수 있다. 간단한 예시를 만들어보자
def func(a,b,**tomato):
  print(a)
  print(b)
  print(tomato)
  
func(1,2,name="hi")

결과
1
2
{'name': 'hi'}

함수 정의할 때 키워드 인수는 반드시 맨 뒤 자리에 위치해야 한다.
그 점 때문에 오류가 난 것이다.
문제의 코드 실행시 아래의 에러가 발생한다.

Traceback (most recent call last):
  File "python", line 1
    def func_param_with_kwargs(name, age, **kwargs, address=0):
                                                    ^
SyntaxError: invalid syntax

그러므로 **kwargs를 맨 뒤자리로 옮겨 문제를 해결할 수 있다.

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)
    
   결과
name=wecode
age=20
kwargs={'mobile': '01012341234'}
address=seoul

위의 코드 실행 시 아래의 오류가 발생한다.

Traceback (most recent call last):
  File "python", line 1
    def mixed_params(name="wecode", *args, age, **kwargs, address):
                                                          ^
SyntaxError: invalid syntax

위 코드는 함수 인자로 positional, default, variable positional, variable keyword, keyword-only 가 총 출동한 예제다.
이 인자들의 순서는 아래와 같다.

위의 순서에 맞게 함수를 바꿔 정의해보자

def mixed_params(age, name="wecode", *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, "wecode", "01012341234", "male" ,mobile="01012341234", address="seoul")

결과는 아래처럼 잘 나온다.
name=wecode
args=('01012341234', 'male')
age=20
kwargs={'mobile': '01012341234'}
address=seoul

참고한 자료
https://getkt.com/blog/python-keyword-only-arguments/
-----------------the end-----------------------------------------

사족)
현재시각 16:28, 아침부터 추가과제와 씨름하다 이제 끝났다. (세션 1시간 30분, 점심시간 1시간 제외)
해결하고 나니까 속이 후련하다.
쉽게 배우면 쉽게 잊히고, 어렵게 익힌 것은 오래 간다는 말로 스스로를 격려한다.

profile
Never stop asking why

0개의 댓글