함수를 호출할 때 입력하는 값(value)를 의미하며,
인자
혹은 전달인자
라고도 한다.
def foo(a, b): # <---- a, b : (매개)변수
print(a, b) # <---- (a, b) : (전달)인자
# 함수 호출
foo(2, 5) # <---- (a, b) : (전달)인자
결과
2 5
위에서 본 함수의 호출 부분을 살펴보자.
foo(2, 5)
인자 2와 인자 5가 함수명 우측에 위치해 있다.
이러한 인자( =전달인자, argument)는
크게 다섯 종류
가 있다.
position argument
def boot_camp(name, course):
print(f'{name}에서 {course}과정을 수강하고 있다.')
boot_camp("wecode", "backend")
결과
wecode에서 backend과정을 수강하고 있다.
만약 인자의 순서를 바꾸면 어떻게 될까?
boot_camp("backend", "wecode")
결과
backend에서 wecode과정을 수강하고 있다.
'인자의 부적절한 위치'에 기인한 잘못된 결과가 나왔다.
keyword argument
def boot_camp(name, course):
print(f'{name}에서 {course}과정을 수강하고 있다.')
boot_camp(course="backend", name="wecode")
결과
wecode에서 backend과정을 수강하고 있다.
위 결과에서 알 수 있듯이
키워드 인자란,
개발자가 직접 인자값(키워드)를 입력했다는 것이다.
이를 통해,
코드의 가독성을 확보할 수 있고,
backend에서 wecode과정을 수강하고 있다.
와 같은
잘못된 결과를 예방할 수 있다.
default argument
def boot_camp(name, course, place="wework 선릉 2호점"):
print(f'{name}에서 {course}과정을 수강하고 있다. 장소는 {place}이다.')
boot_camp("wecode", "backend")
결과
wecode에서 backend과정을 수강하고 있다. 장소는 wework 선릉 2호점이다.
물론, default argument
를 바꿀 수도 있다.
어디까지나 default 값이기 때문이다.
아래 예제로 확인해보자.
def boot_camp(name, course, place="wework 선릉 2호점"):
print(f'{name}에서 {course}과정을 수강하고 있다. 장소는 {place}이다.')
boot_camp("wecode", "backend", "빌딩 10층")
결과
wecode에서 backend과정을 수강하고 있다. 장소는 빌딩 10층이다.
variable length argument
(feat. *args)
(참고) 반드시 args라는 영문명을 사용할 필요는 없음. 중요한 것은 *
def get_sum(*args):
# args는 어떤 값이 담겨 있을까?
print(args)
total = 0
for element in args:
total += element
# 가변인자의 합을 구하자
print(total)
get_sum(-3, -2, -1, 0, 1, 2, 3)
결과
(-3, -2, -1, 0, 1, 2, 3)
0
인자의 개수를 특정하지 않은 경우에 사용된다.
인자가 없을 때 혹은
한 개의 인자만 받을 때 혹은
100 개의 인자를 받을 때 등등 말이다.
특히,
print(args)값을 통해 튜플 자료구조
가 사용되고 있음을 기억하자.
variable length argument
(feat. **kwargs)
def curriculum(**kwargs):
print(kwargs)
curriculum(place="선릉 2호점", course="backend", beverage="coffee")
결과
{'place': '선릉 2호점', 'course': 'backend', 'beverage': 'coffee'}
특히, 결과값을 통해 '딕셔너리'자료구조
가 사용되고 있음을 기억하자.
출처 : https://getkt.com/blog/python-keyword-only-arguments/
def program(camp, course, *args, **kwargs):
print(camp, course, args, kwargs)
## 함수 호출
program("wecode", "backend", "not-frontend", "not sure yet", 기수="9기", name="익명")
결과
wecode backend ('not-frontend', 'not sure yet') {'기수': '9기', 'name': '익명'}
중요한 점은 **kwargs(가변 키워드 인자)가 맨 뒤에 있어야 한다는 것이다.
def boot_camp(name, course, duration):
print(f'{name}에서 {course}과정을 수강하고 있다. {duration} 동안이다.')
boot_camp(duration = "3개월", course="backend", name="wecode")
결과
wecode에서 backend과정을 수강하고 있다. 3개월 동안이다.
함수 호출시, 인자가 모두 키워드 인자로 되어 있을 경우
순서와 상관없이 작동된다.
def boot_camp(name, *args, duration="3개월"):
print(f'{name}의 기수는 {args}다. {duration} 동안이다.')
boot_camp("wecode", "1기", "2기", "3기", "...", "9기", duration = "90 여일")
결과
wecode의 기수는 ('1기', '2기', '3기', '...', '9기')다. 90 여일 동안이다.
위치인자인 "wecode"가 name
에 입력되고, 그 이후의 값들은
가변인자(args)에 입력된다.
중요한 것은 키워드 인자가 가장 마지막에 있어야 한다.
반복 연습하다보면, 인자가 아무리 많은 상황이라도
키워드 인자 앞에 가변 인자가 먼저 나와야 함
을 알 수 있게 된다.
이런 에러 메시지를 많이 만나다 보면 말이다.
TypeError: boot_camp() got multiple values for argument 'duration'
총 정리를 위해 아래 예제를 보자.
함수 정의의 매개변수 부분을 보면
- 위치 인자는 a, b, c로 전달되고,
- 쭉 가다가 가변인자 *more 가 나오고
- 뒤에 키워드 인자도 보인다.
( 즉, 이 이후에 다시 가변인자(*args)가 나오지는 않을 것이다.)- 그리고 어떠한 경우든 가변 키워드 인자(**kwargs)가 가장 마지막에 있어야 한다.
def compute(a, b, c, print_args=True, intype=int, *more, operation, print_result=False, return_type, ignore_exceptions=True, **kwargs):
if print_args:
print(a, b, c, print_args, intype, more, operation, print_result, return_type, ignore_exceptions, kwargs)
result = None
try:
arr = (a, b, c) + more
if operation == "count":
result = len(arr)
elif operation == "sum":
result = sum(arr)
else:
print("Unknow Operation")
raise NotImplementedError("Unknow Operation. Operation Not Implemented")
except:
import sys
print("Error performing operation: {}: {}".format(operation, sys.exc_info()))
if not ignore_exceptions:
raise
if print_result:
print("Result is: {}".format(result))
return result and return_type(result)
Q1. 함수를 정의 할때 default value parameter를
non-default value parameter 앞에 정의 하면 안된다고 배웠습니다.
why?
문제유형 : 디폴트 인자
파이썬 인터프리터가 함수 호출을 할 수 없기 때문이다.(Uncertainty)
디폴트 인자에서 살펴본 예제를 다시 보자.
def boot_camp(name, course, place="wework 선릉 2호점"):
print(f'{name}에서 {course}과정을 수강하고 있다. 장소는 {place}이다.')
boot_camp("wecode", "backend")
그런데 '함수 정의 부분'
이 아래와 같다면?
# 함수 정의
def boot_camp(place="wework 선릉 2호점", name, course):
print(f'{name}에서 {course}과정을 수강하고 있다. 장소는 {place}이다.')
# 함수 호출
boot_camp("wecode", "backend")
첫번째 인자인 "wecode"는
매개변수 place
에 전달돼야 하나? 혹은
매개변수 name
에 전달돼야 하나? 아니면
매개변수 course
에 전달돼야 하는가?
위와 같이 모호한 문제가 발생하므로
다음과 같은 오류 메시지가 나오는 것이다.
"SyntaxError: non-default argument follows default argument"
Q2. '위치인수'와 '가변인수'의 위치를 수정하시오.
유형 : 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("wecode", "01012341234", "seoul", 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("wecode", 20, "01012341234", "seoul")
결과
name=wecode
args=('01012341234', 'seoul')
age=20
위치인수, 가변인수, 키워드 인수 순으로 배치시켜야 한다.
그렇지 않으면
SyntaxError: positional argument follows keyword argument
혹은
TypeError: func_param_with_var_args() got multiple values for argument 'age'
에러를 조우하게 된다.
따라서,
함수 정의는
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("wecode", "01012341234", "seoul", age=20)
결과
name=wecode
args=('01012341234', 'seoul')
age=20
Q3. '가변 키워드 인수' 위치를 수정하시오.
유형 : 위치인자, 디폴트 인자, 가변 키워드 인자
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("wecode", "20", mobile="01012341234", address="seoul")
가변 키워드 인자(**kwargs)의 위치는 맨 마지막이다.
그리고 과제 1번에서 확인했듯이
위치인자가 디폴트 인자보다 먼저 배치돼야 한다.
따라서,
함수 정의는
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("wecode", "20", address="seoul", mobile="01012341234")
결과
name=wecode
age=20
kwargs={'mobile': '01012341234'}
address=seoul
물론!
정해진 답이 있는 것은 아니다.
함수의 매개변수 혹은 함수의 인자값의 위치
를 수정하여
작동이 되도록 얼마든지 수정할 수 있어야 한다.
Q4. 인수의 위치 수정하시오
종합선물세트 유형 : 위치인자, 디폴트 인자, 키워드 인자, 가변 인자, 가변 키워드 인자
우선, 가변 키워드 인자(**kwargs)가 가장 맨 뒤에 배치돼야 함을 알고 있다.
그리고 앞선 과제를 통해
가변인자는 키워드 인자 앞에 배치돼야 하고,
위치인자는 디폴트 인자보다 앞에 배치돼야 함을 배웠다.
따라서,
함수 정의는 아래와 같이 구현할 수 있다.
(위치 -> 가변 -> 키워드 -> 디폴트 -> 가변 키워드),
(위치 -> 가변 -> 디폴트 -> 키워드 -> 가변 키워드) 등등
def mixed_params(age, *args, address, name="wecode", **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, "wecode", "01012341234", "male" ,mobile="01012341234", address="seoul")
이번엔 함수 정의를 (매개변수 부분을) 다음과 같이 수정하였다.
(위치 -> 가변 -> 디폴트 -> 키워드 -> 가변 기워드)
def mixed_params(age, *args, name="wecode", 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)
결과
name=wecode
args=('wecode', '01012341234', 'male')
age=20
kwargs={'mobile': '01012341234'}
address=seoul
- One step at a time -