파이썬은 매우 자유도가 높은 언어이다. 따라서 함수를 사용하면서 인자값에 대해 큰 신경을 쓰지 않아도 에러 없이 편하게 프로그래밍을 할 수 있다. 하지만 그러다가 non-default argument follows default argument 라는 에러를 마주하게 되었고, 이번 기회에 파이썬 함수의 Paramter, Argument의 처리에 관해서 자세히 공부해보기 위해 포스팅을 작성하게 되었다.
https://docs.python.org/ko/3.10/glossary.html 의 parameter, argument 참조.
https://peps.python.org/pep-0570/
https://peps.python.org/pep-3102/
Function Parameter (매개변수, 인수)
Parameter란 함수 정의에서 함수가 받을 수 있는 Arguments를 지정하는 이름 붙은 엔티티이다. 총 5가지 종류의 Parameter가 있다.
1. positional-or-keyword
positional, keyword arguments로 전달될 수 있는 인자를 지정하고, 이것이 파이썬 기본 형태의 파라미터이다. 다음의 foo, bar와 같다.
def func(foo, bar=None): ...
2. positional-only
위치로만 제공될 수 있는 인자를 지정한다. 위치 전용 매개변수는 함수 정의의 매개변수 목록에 / 문자의 앞에 정의할 수 있다. 다음의 posonly1, posonly2와 같다.
def func(posonly1, posonly2, /, positional_or_keyword): ...
3. keyword-only
키워드로만 제공될 수 있는 인자를 지정한다. keyword only 매개변수는 함수 정의의 매개변수 목록에서 앞에 하나의 var-positional 매개변수나 * 를 그대로 포함해서 정의할 수 있다. 다음의 kw_only1, kw_only2와 같다.
def func(arg, *, kw_only1, kw_only2): ...
4. var-positional
(다른 매개변수들에 의해서 이미 받아들여진 위치 인자들에 더하여) 제공될 수 있는 위치 인자들의 임의의 시퀀스를 지정한다. 이런 매개변수는 매개변수 이름에 * 를 앞에 붙여서 정의될 수 있다. 다음의 args와 같다.
def func(*args, **kwargs): ...
5. var-keyword
(다른 매개변수들에 의해서 이미 받아들여진 키워드 인자들에 더하여) 제공될 수 있는 임의의 개수 키워드 인자들을 지정한다. 이런 매개변수는 매개변수 이름에 ** 를 앞에 붙여서 정의될 수 있다. 다음의 kwargs와 같다.
def func(*args, **kwargs): ...
함수에 variable한 paramter까지 포함한다면 최종적으로는 아래와 같은 순서(형태)가 된다.
def func(
posonly1, posonly2, /, a, b=10, *, keyword_only1, keyword_only2, *arg, **kwargs
): ...
Function Arguments (인자)
Argument 란 함수를 호출할 떄 함수로 전달되는 값이다. 두 종류의 인자가 존재한다.
1. keyword argument
함수 호출 때 식별자가 앞에 붙은 인자 (ex: today=) 또는 ** 를 앞에 붙인 딕셔너리로 전달되는 인자이다. 예를 들어, 다음과 같은 leffe() 호출에서 100 과 500 는 모두 keyword argument 이다.
def(today=100, total=500)
def(**{'today': 100, 'total'L 500})
또한, parmteter 이름에 맞추어 값을 넣기 때문에 순서가 바뀌어도 에러가 나지 않고, 어떠한 값을 전달하는지 명확해 가독성도 높다.
2. positional argument
keyword argument 가 아닌 인자이다. positional arugments는 인자 목록의 처음에 나오거나 iterable의 앞에 * 를 붙여 전달할 수 있다. 예를 들어, 다음과 같은 호출에서 100 과 500 은 모두 positional argument 이다.
leffe(100, 500)
leffe(*(100, 500))
keyword argument 보다 뒤에 위치할 경우 에러가 발생하기 때문에 주의해야 한다. (ex: leffe(total=500, 100))
Parameter Default Value
다음은, 내가 개발하면서 겪었던 오류중의 하나와 함께 이야기 해보겠다.
default argument의 경우 non-default argument의 앞에 올 수 없다.
해당 내용의 경우 함수를 호출하거나 선언할 때 그럴 수 없다는 것은 이미 알고 있는 사실이었다. 하지만 나의 경우에 pydantic 을 이용하면서 Model Class를 선언하는 과정에서 해당 에러를 겪었기에 약간 당황했었다. 오류 예제 코드를 살펴보자.
# pydantic model error ❌
class Person(BaseModel):
id: int
name: str = 'Leffe'
height: int = 177
phone: Optional[str]
다음과 같이 모델을 선언할 경우 SyntaxError: non-default argument follows default argument 에러를 맞이하게 된다.
클래스의 경우, __init__() 메서드를 통해 argument가 전달되기 때문에 위의 규칙에 어긋나기 때문에 에러가 발생하는 것이다.
따라서, default argument의 위치를 옮겨 에러를 수정할 수 있었다.
# pydantic model not error ⭕️
class Person(BaseModel):
id: int
phone: Optional[str]
name: str = 'Leffe'
height: int = 177
읽어 주셔서 감사합니다. 공부하면서 정리한 내용이니 틀린 내용이 있을 수 있습니다. 댓글 남겨주시면 감사하겠습니다! :)
'SW개발 > Python' 카테고리의 다른 글
[Python]파이썬 정렬 알고리즘, Timsort (0) | 2022.08.06 |
---|---|
[Python]네임스페이스란(Namespace) ? (0) | 2022.08.06 |
[Python]The Zen of Python - 파이써닉한 코드 (0) | 2021.11.29 |
[Python]TODO 주석 활용법 (feat. 주석 키워드) (0) | 2021.11.24 |
[Python]테스트코드 커버리지 측정 - coverage (0) | 2021.09.27 |