[wecode 3일차] - Function Parameters(Python)

hyuckhoon.ko·2020년 5월 27일
0

What I learned in wecode

목록 보기
32/109

1. argument

1) argument란?

함수를 호출할 때 입력하는 값(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)는
크게 다섯 종류가 있다.


2) argument의 종류

(1) 위치인자

position argument

def boot_camp(name, course):
    print(f'{name}에서 {course}과정을 수강하고 있다.')

boot_camp("wecode", "backend")

결과 wecode에서 backend과정을 수강하고 있다.

만약 인자의 순서를 바꾸면 어떻게 될까?

boot_camp("backend", "wecode")

결과 backend에서 wecode과정을 수강하고 있다.

'인자의 부적절한 위치'에 기인한 잘못된 결과가 나왔다.


(2) 키워드 인자

keyword argument

def boot_camp(name, course):
    print(f'{name}에서 {course}과정을 수강하고 있다.')

boot_camp(course="backend", name="wecode")

결과 wecode에서 backend과정을 수강하고 있다.

위 결과에서 알 수 있듯이
키워드 인자란,
개발자가 직접 인자값(키워드)를 입력했다는 것이다.
이를 통해,
코드의 가독성을 확보할 수 있고,
backend에서 wecode과정을 수강하고 있다. 와 같은
잘못된 결과를 예방할 수 있다.


(3) 디폴트 인자

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층이다.


(4) 가변 인자

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)값을 통해 튜플 자료구조가 사용되고 있음을 기억하자.


(5) 가변 키워드 인자

variable length argument(feat. **kwargs)

def curriculum(**kwargs):
    print(kwargs)

curriculum(place="선릉 2호점", course="backend", beverage="coffee")

결과 {'place': '선릉 2호점', 'course': 'backend', 'beverage': 'coffee'}

특히, 결과값을 통해 '딕셔너리'자료구조가 사용되고 있음을 기억하자.


3) argument 순서

출처 : https://getkt.com/blog/python-keyword-only-arguments/

case 1 : '위치인자', '가변인자', '가변 키워드 인자'

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(가변 키워드 인자)가 맨 뒤에 있어야 한다는 것이다.


case 2 : '키워드 인자'(*args)만 있는 경우

def boot_camp(name, course, duration):
    print(f'{name}에서 {course}과정을 수강하고 있다. {duration} 동안이다.')

boot_camp(duration = "3개월", course="backend", name="wecode")

결과 wecode에서 backend과정을 수강하고 있다. 3개월 동안이다.

함수 호출시, 인자가 모두 키워드 인자로 되어 있을 경우
순서와 상관없이 작동된다.


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



2. 과제

1)

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"


2)

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)

유형 1의 관점으로 보자면

위치인수가 먼저 나오게 하고, 가변인수를 마지막에 배치시키게 한다.
따라서, 함수 정의 부분에서 매개변수를 아래와 같이 수정한다.
(가변인자 맨뒤로 배치)

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

이번엔 유형 2의 관점으로 보자.

위치인수, 가변인수, 키워드 인수 순으로 배치시켜야 한다.

그렇지 않으면
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


3)

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

물론!
정해진 답이 있는 것은 아니다.
함수의 매개변수 혹은 함수의 인자값의 위치를 수정하여
작동이 되도록 얼마든지 수정할 수 있어야 한다.


4)

Q4. 인수의 위치 수정하시오
종합선물세트 유형 : 위치인자, 디폴트 인자, 키워드 인자, 가변 인자, 가변 키워드 인자

우선, 가변 키워드 인자(**kwargs)가 가장 맨 뒤에 배치돼야 함을 알고 있다.
그리고 앞선 과제를 통해
가변인자는 키워드 인자 앞에 배치돼야 하고,
위치인자는 디폴트 인자보다 앞에 배치돼야 함을 배웠다.

따라서,
함수 정의는 아래와 같이 구현할 수 있다.
(위치 -> 가변 -> 키워드 -> 디폴트 -> 가변 키워드),
(위치 -> 가변 -> 디폴트 -> 키워드 -> 가변 키워드) 등등

(1)

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

(2)

이번엔 함수 정의를 (매개변수 부분을) 다음과 같이 수정하였다.
(위치 -> 가변 -> 디폴트 -> 키워드 -> 가변 기워드)

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 - 

0개의 댓글