TIL 9. Python : 위치 인수와 가변 인수

요니·2021년 10월 14일
2

Python

목록 보기
3/7
post-thumbnail

위치 인수란?

위치 인수란 함수를 호출할 때 전달되는 인자들이 매개변수에 순서대로 전달되는 인수를 의미하며 가장 일반적인 방식입니다.

가변 인수란?

가변 인수란 여러 개의 인수의 개수가 변할 수 있는 인수로 함수를 호출할 때 인수의 개수를 다양하게 바꿔가며 전달할 수 있는 방식입니다.

  • 가변 인수(* args)
    여러 개의 일반 인자를 받을 수 있는 인수로 함수 내부에서는 해당 인수를 튜플로 받은 것처럼 인식합니다.

  • 가변 키워드 인수(** kwargs)
    키워드로 이루어진 여러 개의 인자를 받을 수 있는 인수입니다.

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

파이썬 함수의 매개 변수에서 인수를 처리하는 순서는 아래와 같습니다.

  1. positional(non-default) arguments
  2. default arguments
  3. variable length positional arguments (=*arg)
  4. keyword-only arguments
    4-1. non-default keyword-only arguments
    4-2. default keyword-only arguments
  5. variable length keyword arguments (=**kwargs)
1. 앞에서부터 순서대로 지정되는 위치 인자
2. 기본값이 정해져있는 매개 변수
3. 가변 인수(*arg) (예 - list, tuple)
4. 키워드 인수
4-1. 기본값이 정해지지 않은 키워드 인수
4-2. 기본값이 정해져있는 키워드 인수이며 *(asterisk) 뒤에 오는지로 2번과 구분
5. 가변 키워드 인수(**kwargs) (예 - dictionary)

이러한 순서가 있기 때문에 가변 인수를 사용할 때 입력하는 인수들의 순서가 매우 중요합니다.

그렇다면 default value parameternon-default value parameter 앞에 정의하여 한번 호출해봅시다.

def studyClass(first="수학", second, third):
	print(f"{first}{second}는 좋아하고 {third}를 싫어한다.")
    
studyClass("과학", "영어")

# Error
  File "main.py", line 1
    def studyClass(first="수학", second, third):
    
  SyntaxError: non-default argument follows default argument

호출해보니 SyntaxError가 나타납니다.
아직 값이 없는 나머지 parameter에 순서대로 들어가면 될 것 같은데 왜 오류가 발생할까요?

default value parameter가 있으면 실제 parameter의 개수보다 적은 parameter를 입력하게 되며 기본적으로 positional arguments를 따르기 때문에 순차적으로 인수가 할당되어야 합니다.

studyClass 함수의 첫번째 인자가 'first' 로 이동해야 하는데, 'first' 는 이미 "수학"이라는 default value가 있습니다.

default value가 있지만 positional arguments를 따라 'first' 와 'second' 에 "과학"과 "영어"가 이동하게 되고 마지막인 'third'가 공석이 됩니다.

parameter 내부의 인자 중 default argument가 앞 쪽에 위치하게 된다면 인자가 들어갈 곳이 모호해지는 것입니다.

이러한 일들을 방지하고자 함수에서 non-default value parameterdefault value parameter 보다 앞으로 오도록 설계해야 합니다.

그렇다면, 위치 인수와 가변 인수의 위치를 참고하여 함께 함수의 오류를 수정해볼까요?!

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)

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

이 코드는 왜 오류가 났을까요?

* args는 여러 개의 인자를 받을 수 있는 가변 인수이기 때문에 사용자가 몇 개의 인수를 입력할지 알 수 없어서 * args 보다 뒤에 위치한 'age'에게 할당할 인자를 남기지 않고 모두 다 가져가게 됩니다.

그렇기 때문에 뒤에 있던 non-default value parameterdefault value parameter 보다 앞에 정의해 주어야 합니다.

그렇다면 age와 * args의 순서를 바꾸어 볼까요?

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

아래와 같이 오류 없이 정상적으로 결과가 나왔습니다. :)

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

이번엔 가변 키워드 인수와 default value parameter가 있는 경우에 발생한 함수의 오류를 수정해봅시다.

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

# Error
  File "main.py", line 1
    def func_param_with_kwargs(name, age, **kwargs, address=0):
                                                    
  SyntaxError: invalid syntax

이 코드는 왜 오류가 났을까요?

파이썬은 **kwargs를 가장 마지막으로 처리하여야 하나 가변 키워드 인수인 **kwargs 뒤에 default값을 가진 address가 위치해 있기 때문에 Error가 발생하였네요.

이 때 address는 default값을 가지기 때문에 위치 인자인 name과 age보다 앞에 위치하지 않도록 주의해야 합니다.

그렇다면 address와 ** 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")

아래와 같이 오류 없이 정상적으로 결과가 나왔습니다. :)

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

마지막으로 위치 인수와 키워드 가변 키워드 인수의 위치를 참고하여 함수의 오류를 수정해봅시다.

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

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

이번엔 왜 오류가 났을까요?

위치 인수인 age를 제일 앞으로 이동해야하며 키워드 인수인 address는 가변 인수보다는 뒤이고 가변 키워드 인수보다는 앞에 위치해야 합니다.

그렇다면 순서를 바꾸어 볼까요?!

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

짜잔! 아래와 같이 오류 없이 정상적으로 결과가 나왔습니다. :)

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

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

profile
내가 나여서 빛이나기 위해😊

1개의 댓글

comment-user-thumbnail
2021년 10월 15일

👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏

답글 달기