파이썬의 함수는 정말 다양한 형태의 인자를 받습니다.
인자값의 기본값 유무에 따라
non-default value parameter와 default value parameter로 나뉘기도 하면서,
이 두 인자형태를 여러개 받을 수 있는 *args와 **kwargs로 나뉘기도 합니다.
좀 더 정확한 설명을 위해 (non)/default value parameter부터 살펴봅시다.
non-default value parameter는 미리 값이 정해지지 않은 인자입니다.
가장 흔하게 쓰이는 인자타입이기도 한데,
함수를 호출할 때 인자의 순서대로 인자값을 넣어주어야 합니다.
def use_non_default_value_parameter(name, occupation):
return f'내 이름은 {name}, {occupation}이죠.'
# 의도대로 인자의 순서를 맞추지 않으면...
print(use_non_default_value_parameter('탐정', '코난'))
# 결과
# 내 이름은 탐정, 코난이죠.
위 결과에서 보여지는 non-default value parameter의 단점은 아래와 같습니다.
하지만 순서만 잘 맞춘다면 정말 자유롭게 값을 받아 쓸 수 있습니다.
함수 선언시 미리 값이 정해지는 인자입니다.
기본값이 존재하는 인자를 받을때 사용하며
코드의 중복을 줄이고 가독성을 높이기 위해 주로 사용합니다.
def use_default_value_parameter(count, last='땡!'):
for i in range(count, 0, -1):
print(i)
print(last)
use_default_value_parameter(5)
# 결과
5
4
3
2
1
땡!
물론 default value가 정해졌다 해도
언제든 함수 사용시 값을 변경할 수 있습니다.
def use_default_value_parameter(count, last='땡!'):
for i in range(count, 0, -1):
print(i)
print(last)
use_default_value_parameter(5, '1의 반.. 1의 반의 반...')
# 결과
5
4
3
2
1
1의 반.. 1의 반의 반...
이 이유때문에
default value parameter는 항상 non-default value parameter보다 뒤에 위치해야 합니다.
2개의 인자를 가진 func 라는 함수를 작성해봅시다.
하나는 기본값을 가진 인자고, 하나는 그렇지 않은 인자입니다.
# 잘못된 코드
def func(x = 1, y):
print(x, y)
func(2)
위 코드는 y의 값을 2로 지정해줄 의도였지만
default value를 가진 parameter도 값이 변경 가능하기 때문에
func(2)의 2는 x에게 할당됩니다.
따라서 y는 아무런 값을 할당받지 못하니 에러가 나고 맙니다.
# SyntaxError: non-default argument follows default argument
non-default value parameter의 개수가 유동적일때 사용합니다.
입력받은 인자들은 튜플 형태로 저장됩니다.
def func(*args):
return args
print(func(1, 3, ['1', 2], {'a':1}, 1000.10))
# 결과: (1, 3, ['1', 2], {'a': 1}, 1000.1)
따라서 *args 인자 뒤에 다른 인자가 있으면 에러가 납니다.
*args는 앞의 인자에 할당하고 남은 나머지 전부를 가져가기 때문에
그 뒤의 인자가 할당받을 것이 없기 때문입니다.
# 에러가 날 함수
def func_param_with_var_args(name, *args, age):
print(f"name={name}")
print(f"args={args}")
print(f"age={age}")
func_param_with_var_args("정우성", "01012341234", "seoul", 20)
# '정우성'은 name에 배정되고, '01012341234' 부터 20까지 *args에 배정된다.
#결과: TypeError: func_param_with_var_args() missing 1 required keyword-only argument: 'age'
하지만 *args 뒤에 default value를 가진 인자가 오면
해당 인자는 args에 포함되지 않습니다.
뒤에 언급되겠지만,
default value parameter는 *args가 아니라 **kwargs에 포함되기 때문입니다.
# 수정된 함수
def func_param_with_var_args(name, *args, age=20):
print(f"name={name}")
print(f"args={args}")
print(f"age={age}")
func_param_with_var_args("정우성", "01012341234", "seoul")
# 결과
# name=정우성
# args=('01012341234', 'seoul')
# age=20
default value parameter의 개수가 유동적일때 사용합니다.
입력받은 인자들은 딕셔너리 형태로 저장됩니다.
def func(**kwargs):
return kwargs
print(func(lang='python', number=1000, dictionary={'a':1, 'b':2}))
# 결과: {'lang': 'python', 'number': 1000, 'dictionary': {'a': 1, 'b': 2}}
**kwargs는 *args와 마찬가지로 앞의 인자들이 할당을 받은 후
남은 나머지들을 모두 가져가기 때문에 맨 뒤의 순서에 위치해야 합니다.
**kwargs는 사실상 함수의 인자 중 가장 마지막으로 오는 인자입니다.
따라서 뒤에 다른 인자가 붙으면 syntax error가 발생합니다.
# 수정한 함수
def func_param_with_kwargs(name, age, address=0, **kwargs):
print(f"name={name}")
print(f"age={age}")
print(f"kwargs={kwargs}")
print(f"address={address}")
func_param_with_kwargs("정우성", "20", mobile="01012341234", address="seoul")
# 결과
# name=정우성
# age=20
# kwargs={'mobile': '01012341234'}
# address=seoul
이 네 가지 인자형태를 동시에 받으려면 인자 순서는 어떻게 정해줄까요?
조금 복잡하게 느껴질 수도 있지만 간단합니다.
1. 우선 *args 이전의 인자들이 각자 하나의 값씩을 배정받을 것이고,
2. 남은 non-default value parameter들은 *args에 포함될 것입니다.
3. 그럼 이제 default value parameter들만 남는데,
그 중 함수 선언때 썼던 인자의 이름(key)이 일치하는 게 있으면 먼저 값을 배정받습니다.
4. 남은 default value parameter들이 **kwargs로 들어갑니다.
def mixed_params(age, name="아이유", *args, address, **kwargs):
print(f"name={name}")
print(f"args={args}")
print(f"age={age}")
print(f"kwargs={kwargs}")
print(f"address={address}")
mixed_params(20, "정우성", "01012341234", "male", mobile="01012341234", address="seoul")
# 결과
# name=정우성
# args=('01012341234', 'male')
# age=20
# kwargs={'mobile': '01012341234'}
# address=seoul
[python]패키지, 모듈 (0) | 2021.03.18 |
---|---|
[python]튜플, 왜 쓰는걸까? (1) | 2021.03.18 |
[Python] 문자열을 붙이는 다양한 방법 (string concatenation) (1) | 2021.03.17 |
파이썬 매직 메소드(던더 메소드) (2) | 2021.02.28 |
파이썬 예외처리 (try, except, else, finally, assert) (0) | 2021.02.26 |
댓글 영역