TIL | Python - parameter(default value VS non-default value)

송치헌·2021년 8월 5일
0
post-thumbnail

무엇을 배웠는가?

문제 1.

default value parameter

함수의 파라미터를 입력할 때 인자로 넘어온 값이 없을 경우 기본값으로 쓸 파라미터 값을 정해주는 것
예를 들면,

def add(a,b=3):
    return a+b

print(add(3)) #6

참고로 parameters는 함수 선언할 때 받아오는 값이고, arguments는 함수를 호출할 때 넘겨주는 값이다. 엄청 크게 중요하지는 않은 것 같지만 알아두면 좋다.

여기서 add함수의 파라미터는 2개를 설정해 주었지만 argument로 넘겨주는 인자는 1개밖에 없다. 그 이유는 이미 add함수의 파라미터에 b=3이라고 default값을 설정해 주었기 때문이다.

그렇다고 1개만 넣어야 하냐?! 그것도 아니다. 말 그대로 default값이기 때문에 '너가 값을 안넣어 준다면 내가 알아서 설정된 기본값으로 넣을게!' 라고 하는 것이다. 즉, print(add(3,5))라고 하면 8이 출력된다.

non default value parameter

위 예시 코드에서 a파라미터에는 아무 것도 설정해 주지 않았다. 저 a가 non default value parameter이다. a의 경우에는 함수를 호출할 때 인자값을 설정해 주지 않으면 에러가 난다.

순서를 바꿔보자

위 예시 코드에서 파라미터의 순서를 바꾸면 무슨 일이 일어나는지 살펴보자.

def add(a=2, b):
    return a+b

print(add(3))

  File "main.py", line 27
    def addd(a=2, b):
             ^
SyntaxError: non-default argument follows default argument

non-default argument가 defualt argument뒤에 온다고 한다. 그럼 오류가 나나보다.

그 이유는 파이썬에서 함수를 선언할 때 파라미터의 우선 순위가 존재한다.

우선 순위는 다음과 같다.

def example(a,b,c=None,r="w",d=[],*ae,**ab):

a, b : positional parameter
c : optional parameter
r : keyword parameter
d: list parameter
*ae : keyword only
**ab : var-keyword parameter

따라서 순서를 잘 지켜서 함수를 설정해 주어야 에러가 나지 않는다.

다시 위의 예를 보면

def add(a=2, b):
    return a+b

print(add(3))

  File "main.py", line 27
    def addd(a=2, b):
             ^
SyntaxError: non-default argument follows default argument

여기서 a=2로 디폴트 값만 준 것이지 값을 변경하지 못하는 것은 아니다. 따라서 함수를 호출할 때 인자값으로 a를 변경할 수 있는데 add(3)에서 3이 a를 바꿔준 것인지 b를 바꿔준 것인지 컴퓨터는 알 수 없기 때문에 순서에 맞게 설정해 주는 것이 중요하다.

positional arguments(위치 인자) & variable length arguments(가변 인자)

positional arguments(위치 인자) : 위치가 정해진 인자이다.

def exam(a,b,c):
    print(a,b,c)
exam(3,1,2) #3,1,2

여기서 a, b, c는 포지셔널 아규먼트이다. 즉, 순서가 정해져 있기 때문에 순서대로 인자가 입력이 된다. a에는 3, b에는 1, 마지막으로 c에는 2가 들어가게 된다.

variable length arguments(가변 인자) : 원하는 만큼 넣을 수 있는 인자

def var_len_args(a,b,*args):
    res = 0
    for num in args:
        res += num
    print(a+b+res)
var_len_args(1,2,3,3,3,3) #15

ab까지는 positional arguments로 설정이 되었다. 그러나 그 뒤에 *args가 있다. 이게 바로 가변 인자를 받는 파라미터이다. a는 1, b는 2, 나머지 3,3,3,3은 *args에서 모조리 다 받아주는 것이다.

우리가 print(1,2,3,4,5,6,7)이라는 print함수를 쓸 때도 안에 몇개씩이나 넣을 수 있는 이유가 print함수가 가변 인자를 넣어주기 때문이다.

또한 가변 인자를 keyword arguments로 넣을 수도 있다. 그럴 때는 **kwargs를 파라미터로 여러 keyword arguments를 받는다.

def keyword_arguments(a, b, **kwargs):
    for key, val in kwargs.items():
        print(f"{key}={val}")
keyword_arguments("hi", "hello", c="bye", d="good", e="happy") 
#결과
'''
c=bye
d=good
e=happy
'''

이런 식으로 keyword arguments로 여러개 받아서 사용하는 가변 인자도 있다. 참고로 c="bye", d="good", e="happy" 이 부분을 받아올 때 딕셔너리로 받아오게 된다.
이전에 작성한 TIL | Get Ready for Django - 1 에서 자세하게 설명한 것이 있다.


문제 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", 20)



Traceback (most recent call last):
  File "main.py", line 32, in <module>
    func_param_with_var_args("정우성", "01012341234", "seoul", 20)
TypeError: func_param_with_var_args() missing 1 required keyword-only argument: 'age'

keyword-only argument가 하나 없다고 나온다. 하나씩 살펴보자.

func_param_with_var_args("정우성", "01012341234", "seoul", 20)
여기서 인자들은 모두 positional argument이므로 함수의 파라미터에 이 순서대로 매핑해서 넣으면 된다.
먼저, name에 "정우성"이 들어간다.

그 다음에 *args에는 계속 인자가 들어올 수 있다. "01012341234", "seoul", 20 이 세개의 인자를 모두 *args에 넣어준다.

이제 인자를 다 넣어주었으니 함수가 돌아가면 되는데 age에는 아무런 인자도 들어오지 않았다. optional parameter도 아니기 때문에 결국 에러가 난다.

여기서 문제는 바로 *args를 중간에 넣어주었기 때문에 몇개의 인자까지 넣어야 하는지 모른다.
그래서 컴퓨터는 그냥 positional arguments가 나오는 대로 모조리 집어 넣은 것이고 그 결과, age에 들어올 인자가 없던 것이다.

수정해보자.

  1. *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("정우성", 20, "01012341234", "seoul")

#결과
'''
name=정우성
args=('01012341234', 'seoul')
age=20
'''

이름과 나이를 넣어주고 나머지를 *args에 넣어주었다.

  1. age를 받아올 인자에 키값을 주어 *args에 들어가지 못하게 해준다.
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)

#결과
'''
name=정우성
args=('01012341234', 'seoul')
age=20
'''

문제 3.

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

위에 파라미터 우선 순위 부분에서 설명했듯 함수 정의가 잘못 되었다.

따라서 다음과 같이 수정하면 된다.

수정해보자.

  1. keyword parameter를 var keyword parameter앞으로 이동시킨다.
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")

#결과
'''
name=정우성
age=20
kwargs={'mobile': '01012341234'}
address=seoul
'''

문제 4.

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



  File "main.py", line 27
    def mixed_params(name="아이유", *args, age, **kwargs, address):
                                                       ^
SyntaxError: invalid syntax

이 문제도 함수 파라미터 정의하는 부분이 잘못되었다.

수정해보자.

def mixed_params(age, address, name="아이유", *args, **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,"seoul", "정우성", "01012341234", "male" ,mobile="01012341234")

#결과
'''
name=정우성
args=('01012341234', 'male')
age=20
kwargs={'mobile': '01012341234'}
address=seoul
'''

파라미터의 선언 순서와 그에 맞게 인자들의 순서도 바꾸어 주었다.

어디에 적용했는가?

파이썬 과제를 수행하는데 적용했다. 이 부분은 매우 중요한 부분이라 꼭 알고 넘어가야 한다고 생각한다.
나중에 Django나 Flask를 배울 때 분명히 나올 것 같다.

어려웠던 점은 무엇인가?

전반적으로 다 어려웠다. *args와 **kwargs를 공부했었지만 이렇게 까지 복잡한줄은 몰랐다.

profile
https://oraange.tistory.com/ 여기에도 많이 놀러와 주세요

0개의 댓글