[Pre-course] 2021. 10. 07-1

GYUBIN ·2021년 10월 7일
0

Python

Function Parameters


  1. positional arguments

순서대로 값이 parameter로 함수에 전해진다

def love(my_name, your_name):
    print(f"{my_name} loves {your_name}")
# my_name = parameter1, your_name = parameter2
love("Kim", "Lee")
# 출력값
# Kim loves Lee

  1. Keyword Arguments

parameter 이름으로 맞추어서 값을 전해준다

def love(my_name, your_name):
    print(f"{my_name} loves {your_name}")
# my_name = parameter1, your_name = parameter2
love(your_name = "Lee", my_name = "Kim")
# 출력값
# Kim loves Lee

Keyword arguments는 위 예시처럼 parameter 순서가 바뀌어도 괜찮다


  1. Mixing positional arguments and keyword arguments

positional arguments와 keyword arguments를 혼용하여 사용하는것도 가능하다

def love(my_name, your_name):
    print(f"{my_name} loves {your_name}")
# my_name = parameter1, your_name = parameter2
love("Kim", your_name = "Lee")
# 출력값
# Kim loves Lee

여기서 중요한 점은 keyword arguments 는 순서가 바뀌어도 상관 없지만 positional arguments 부분은 순서를 지켜줘야 한다는 것이다


  1. Parameter Default Value

함수의 parameterdefault 값을 정의해 줄 수 도 있다

def love(my_name, your_name = "Lee"):
    print(f"{my_name} loves {your_name}")
# my_name = parameter1, your_name = parameter2
love("Kim")
# 출력값
# Kim loves Lee

여기서도 중요한 점은 default 값이 정의된 parameterdefault 값이 정의 되지 않은 parameter보다 앞에 위치해 있으면 안된다는 것이다



   ❓❗    default value parameter를 non-default value parameter 앞에 정의 하면 안 되는 이유

  1. Parameter Default Value를 예시로 가져와 보자
def love(my_name, your_name = "Lee"):
    print(f"{my_name} loves {your_name}")
# my_name = parameter1, your_name = parameter2
love("Kim")
# 출력값
# Kim loves Lee


default value parameternon-default value parameter의 순서를 바꿔보면

def love(my_name = "Kim", your_name):
    print(f"{my_name} loves {your_name}")
# my_name = parameter1, your_name = parameter2
love("Lee")
# 출력값
# SyntaxError: non-default argument follows default argument

에러가 발생하게 된다

이유가 무엇일까?

< careerkarma 참고 >

이론적인 것을 먼저 살펴보자면 Python 함수에서 인수가 표시되어야 하는 순서는 다음과 같다

  1. Positional arguments (non-default)
  2. Keyword arguments (default)
  3. Keyword-only arguments (*args)
  4. Variable keyword arguments (**kwargs)

이 순서를 따르지 않으면 Python은 오류 메시지를 반환한다

단순하게 공식으로만 생각해보면 2순위(default)가 1순위(non-default)보다 앞에 위치해 있어서 에러가 발생하게 되는 것이다

공식으로 해결하지 않고 에러가 발생하는 이유에 대해 고민해보니 non-default를 앞에 위치시키고 input을 주게 된다면 Python은 input이 어느 곳으로 가야하는지 알 수 없겠다는 생각이 들었다

위 에러 내용을 다시 정리해보면

def love(my_name = "Kim", your_name):
    print(f"{my_name} loves {your_name}")
# my_name = parameter1, your_name = parameter2
love("Lee") # 여기서 "Lee"는  my_name ? or your_name?

즉 my_name이 "Lee"인지 your_name이 "Lee"인지 알 수가 없기 때문인다

def love(your_name, my_name = "Kim"):
    print(f"{my_name} loves {your_name}")
# my_name = parameter1, your_name = parameter2
love("Lee")
# 출력값
# Kim loves Lee

이렇게 작성하면 "Lee"는 your_name에 해당한다는 것을 바로 이해할 수 있고 my_name = "Kim"이 default 값으로 정의되어 있어서 Kim loves Lee가 올바르게 출력되는 것을 볼 수 있다 !


추가 정보 !! ( * 사용 시 SyntaxError 발생 X)

검색을 하다가 추가적인 정보를 발견했다

1. Positional arguments (non-default)
2. Keyword arguments (default)
3. Keyword-only arguments (*args)
4. Variable keyword arguments (**kwargs)

위 순서와 상관없이 def love(my_name = "Kim", your_name):에서 *my_name = "Kim" 앞이나 뒤에 추가로 입력해주고 love(your_name = "Lee") 처럼 default 값으로 input이 되면 오류가 발생하지 않는다는 것이다

코드로 바로 살펴보자

def love(*, my_name = "Kim", your_name):
    print(f"{my_name} loves {your_name}")
love(your_name = "Lee")
# 출력값
# Kim loves Lee

이유가 무엇인지는 아직은 잘 모르겠다..
추후에 관련 내용에 대해 이해하게 되면 추가로 포스팅 하겠다 !




개념 이해를 했으니 실전을 통해 지식을 다져보자

1. 위치 인수(positional arguments)와 가변 인수(variable length 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)
# 출력값
# TypeError: func_param_with_var_args() missing 1 required keyword-only argument: 'age'

대충 해석해보면 'age' 값이 요구된다, 'age'의 값이 없다 로 이해할 수 있다

그러면 'age'를 모두 삭제하고 진행해보자

def func_param_with_var_args(name, *args):
    print("name=",end=""), print(name)
    print("args=",end=""), print(args)
func_param_with_var_args("정우성", "01012341234", "seoul", 20)
# 출력값
# name=정우성
# args=('01012341234', 'seoul', 20)

정상적으로 출력되는 것을 확인 할 수 있고 'args'가 args=('01012341234', 'seoul', 20) 까지 모두 포함하고 있는 모습.
즉, 'age' 값에 해당하는 20까지 갖는 것을 알 수 있다

에러를 해결하기 위해서는 아래 두가지를 생각해 보았다

1. func_param_with_var_args("정우성", "01012341234", "seoul", 20)func_param_with_var_args("정우성", "01012341234", "seoul", age =20) 으로 변경해서 (age =20) 을 default 로 적용시키는 방법
2. 'age'와 해당하는 값인 20을 'args'와 ("01012341234", "seoul")보다 앞에 위치시키는 방법

실제 코드로 작성해보면 두 가지 방법 모두 정상 출력 되는 것을 확인 할 수 있다

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

2. 가변 키워드 인수 (variable length keyword arguments)의 위치 에러 수정

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")
# 출력값
# SyntaxError: invalid syntax

에러 내용은 구문 오류로 Python 문법에 맞지 않다는 뜻이다
그렇다면 어느 부분에서 에러가 발생했을까?

1. Positional arguments (non-default)
2. Keyword arguments (default)
3. Keyword-only arguments (*args)
4. Variable keyword arguments (**kwargs)

문법 이론을 다시 가져와 봤다
default 값인 'address=0' 보다 **kwargs 값인 'kwargs'가 앞에 위치한 것이 문제인 것을 확인 할 수 있다

def func_param_with_kwargs(name, age, **kwargs, address=0):def func_param_with_kwargs(name, age, address=0, **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)
func_param_with_kwargs("정우성", "20", mobile="01012341234", address="seoul")
# 출력값
# name=정우성
# age=20
# kwargs={'mobile': '01012341234'}
# address=seoul

3. 위치 인수와 키워드 가변 키워드 인수 (variable length keyword arguments)의 위치 에러 수정

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")
# 출력값
# SyntaxError: invalid syntax

이번에도 문법에 오류가 있다

2. 가변 키워드 인수 (variable length keyword arguments)의 위치 에러 수정과 동일하게 'kwargs'가 'address' 보다 앞에 위치하고 있어서 생긴 에러이다

수정을 해주면

def mixed_params(name="아이유", *args, age, 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")
# 출력값
# TypeError: mixed_params() missing 1 required keyword-only argument: 'age'

여전히 에러가 뜨는데 어디서 많이 본 에러다

1. 위치 인수(positional arguments)와 가변 인수(variable length arguments)의 위치 에러 수정과 동일하게 'age'에 해당하는 값이 없어서이다

수정을 해주면

def mixed_params(name="아이유", *args, age, 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(age = 20, "정우성", "01012341234", "male" ,mobile="01012341234", address="seoul")
# 출력값
# SyntaxError: positional argument follows keyword argument

default 값인 (age = 20) 이 non-default 값인 ("정우성", "01012341234", "male") 보다 앞에 위치하고 있어서 에러가 또다시 발생하였다 두 값의 순서를 바꿔주면 모든 에러가 해결이 되는 것을 볼 수 있다

def mixed_params(name="아이유", *args, age, 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("정우성", "01012341234", "male", age = 20, mobile="01012341234", address="seoul")
# 출력값
# name=정우성
# args=('01012341234', 'male')
# age=20
# kwargs={'mobile': '01012341234'}
# address=seoul

사실 아직까지 내가 이해한 이론적인 개념으로만 따지면 위 코드에서도 def mixed_params(name="아이유", *args, age, address, **kwargs):를 보면 default 값인 name="아이유" 가 non-default 값인 age, address 보다 앞에 위치해 있기에 문제가 있어야 한다고 생각이 든다

하지만 추가 정보 !! 에서 * 사용 시 SyntaxError 가 발생하지 않는 것을 확인했기 때문에 일단은 넘어가지만 이유가 뭔지는 꼭 알아봐야겠다

0개의 댓글

관련 채용 정보