[Python] 1_Function Parameters

dev.soo·2020년 8월 21일
0
post-thumbnail

함수를 정의하고 호출할 때는 변수Parameter 와 인수argument 를 사용한다.

parameter (매개변수)
함수의 정의 부분에 나열되어 있는 변수, 여기서는 plus 함수 정의시에 사용되는 a, b를 parameter(매개변수) 라고 한다.
def plus(a, b):
     return a + b

argument (전달인자)
함수를 호출할때 전달 되는 실제 값, 여기서는 plus 라는 함수에 넣어주는 값 1, 2를 argument(전달인자)라고 한다.
result = plus(1, 2)

그 중 함수를 호출할 때 전달인자를 아래와 같이 사용하는 경우를 살펴보겠다.

Arguments

1) Only Positional arguments
2) Only Keyword arguments
3) Positional arguments and Keyword arguments

1) Only Positional arguments

Positional 이라고 했으니 당연히 순서가 중요하다. 아래의 meal 함수를 살펴보면,

def meal(menu, whom, time):
  print(f"Let's eat {menu} with {whom} at {time}pm")
   
meal("pizza", "me", 3)

메뉴, 사람, 시간을 함수에 순서대로 넣어 호출했다.

meal(3, "me", "pizza")라고 인자들의 순서를 바꾸어 함수를 호출하면 함수가 실행되긴 하지만 "Let's eat 3 with me at pizza time"이라는 엉뚱한 결과가 나타나, 순서에 유의하여 전달 인자를 넣어주어야 한다.

2) Only Keyword argument

 def meal(menu, whom, time):
  print(f"Let's eat some {menu} with {whom} at {time}pm")
   
meal(menu="pizza", time=3, whom="me")

함수의 각 parameter 에 구체적으로 argument 가 지정되었다. 이제 모두 이름이 붙었으니 순서는 중요하지 않다. 이렇게 되면 실수로 값이 바뀔 확률이 상대적으로 적다. 또한 코드를 읽는 사람도 어떠한 값을 넘기는건지 명확하게 알 수 있기 때문에 가독성도 높아진다.

3) Positional argument and Keyword argument

이 경우는 Positional argument 가 포함되어 있으니 순서가 다시 중요해 진다. 순서가 정확하지 않으면 에러가 난다.

순서 : positional argument + keyword argument

순서에 맞게 호출한 경우

def meal(menu, whom, time):
  print(f"Let's eat some {menu} with {whom} at {time}pm")

# p + k + k (keyword argument 는 순서 뒤죽박죽)
meal("pizza", time=3, whom="me")

# p + p + k 
meal("pizza", "me", time = 3)

오류가 나는 경우

 def meal(menu, whom, time):
   print(f"Let's eat some {menu} with {whom} at {time}pm")

# k + p + k
meal(time = 3, whom="me", "pizza") 

# k + k + p

meal(menu="pizza", whom = "me", 3) 

# k + p + p 
meal(menu ="pizza", 3, "me")

지금까지는 함수 호출시 parameter 에 할당되는 arguments 에 대해서 살펴보았다.

Parameters

이번에는 함수 정의 단계에서 parameters 에 대해 살펴보자.

1) Non-default value parameter : 위의 meal(menu, whom, time) 함수처럼 값을 함수 정의 단계에서 할당하지 않고 함수를 호출할 때 지정해줌
2) Default value parameter : parameter 에 값을 default로 지정하여 함수를 정의

Default value parameter

함수가 default value 를 parameter 로 가질 때의 parameter 를 default value parameter 라고 할 수 있다.
아래 meal 함수는 menu, whom, time 값을 default 로 이미 가지고 있다.

def meal(menu="pizza", whom="me", time=3)
  print(f"Let's eat some {menu} with {whom} at {time}pm")
  
meal() 
#Let's eat some pizza with me at 3pm

Parameter 가 default 라는 것은, 함수를 호출할 때 전달인자를 생략할 수도 있고 아닐수도 있다는 말이다.

def meal(menu="pizza", whom="me", time=3)
 print(f"Let's eat some {menu} with {whom} at {time}pm")
 
# Positional and keyword arguments (non-default values)
meal("pizza", time=3, whom="me")

# Positional arguments (non-default values)
meal("pizza", "me", 3) 

default value parameter 를 사용하여 함수를 정의할 때는 (호출 아님) 아래 순서를 지키지 않으면 Error 가 난다.

순서 : non-default value parameter + default value parameter

파이썬 공식 홈페이지에서는 아래와 같이 설명하기도 한다.

If a parameter has a default value, all following parameters must also have a default value -- this is a syntactic restriction that is not expressed by the grammar.

왜??

default value parameter 가 있으면 실제 parameter의 개수보다 적은 argument 를 입력하는 게 가능해 지고, 이 때 생략된 non-default value parameter에 argument가 순서대로 입력되는데 어느 parameter에 전달되는 인자인자 알 수 없기 때문이다.



Variable length arguments

지금까지 살펴본 함수는 모두 함수 정의를 정의할 때 parameter 의 갯수가 정해져 있고 전달인자도 이 갯수에 맞게 넣어서 함수를 호출했다.

이번에는 함수를 정의할때 parameter 를 정하지 않고 함수 호출과 동시에 parameter 의 갯수가 정해지는 함수를 살펴보겠다. 이때는 가변 인수(variable length arguments)를 사용하는데 통상적으로 약자인 args에 ""를 1개 붙여 "args" 를 사용한다. 이 때의 arguments 는 positional arguments 이다.

def func(*args):
    print(args)
    
func(1,2,3,4)
# 결과값 -> (1,2,3,4)

func(1,2,3)
# 결과값 -> (1,2,3)

def func(*args):
    print(*args)
    
func(1,2,3,4)
# 결과값 -> 1 2 3 4

이 처럼 호출시 전달인자(argument)가 3개일 수도 있고 4개일 수도 있는 함수를 만들었다. 그럼 아래와 같은 함수도 가능할까?

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)


결과
Traceback (most recent call last):
  File "c:/Users/ASUS/Desktop/코딩/책/ddd.py", line 7, in <module>
    func_param_with_var_args("정우성", "01012341234", "seoul", 20)
TypeError: func_param_with_var_args() missing 1 required keyword-only argument: 'age'

keyword 를 argument 로 받는 parameter "age" 의 값이 할당되지 않아서 Error 가 났다.

"age"에 keyword argument 를 할당하여 함수 호출부분만 고쳐 다시 실행해 보았다.

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", age=20)

결과
name=정우성
args=('01012341234', 'seoul')
age=20

positional argument 만 사용하기 위해 가변 키워드 인수가 아닌 가변 인수를 뜻하는 *args 를 사용하였는데, 이렇게 되면 keyword argument 가 함께 사용되게 된다.

positional arguments 만 사용하기 위해서는 parameter 를 고쳐야 한다.

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)

결과
name=정우성
args=('seoul', 20)
age=01012341234

값이야 어떻게 됐든, positional arguments 가 앞에서부터 순서대로 각 parameter 에 전달되었다.

Variable keyword arguments


이번에는 가변 키워드 인수를 알아보자. 가변 키워드 인수를 사용하면 함수 호출시 Keyword argument 를 몇 개고 받을 수 있다.
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")

결과
    def func_param_with_kwargs(name, age, **kwargs, address=0):
                                                    ^
SyntaxError: invalid syntax

syntax 오류가 나서 kwargs 사용시의 문법을 찾아보았다. kwargs는 *args사용시의 문법과 비슷하지만 그 갯수를 function argument 내에 함께 작성해야 한다.

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

결과
    def func_param_with_kwargs(name, age, **kwargs, address=0):
                                                    ^
SyntaxError: invalid syntax

위처럼 kwargs가 Positional arguments 보다 앞에오면 에러가 난다. kwargs를 뒤에 배치해서 함수를 호출해야 한다.

def func_param_with_kwargs(name, age, address=0, **kwargs):
    print("name=",end=""), print(name)
    print("age=",end=""), print(age)
    print("address=",end=""), print(address)
    print("kwargs=",end=""), print(kwargs)
    


func_param_with_kwargs("정우성", "20", address="seoul", mobile="01012341234")

결과
name=정우성
age=20
address=seoul
kwargs={'mobile': 1012341234}

*args and **kwargs

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


결과
 def mixed_params(name="아이유", *args, age, **kwargs, address):
                                                       ^
SyntaxError: invalid syntax

*args 와 kwargs 를 포함한 함수를 정의하였더니 함수 정의시 kwargs에서 다시 문법오류가 났다.

함수의 parameters 를 아래와 같이 변경하고 실행해보았다.

def mixed_params(age, address, name="아이유", *args, **kwargs):


#순서: Positional arguments 
#-> keyword arguments 
#-> Variable length arguments 
#-> Variable keyword arguments 

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

결과:
    mixed_params(20, "정우성", "01012341234", "male" ,mobile="01012341234", address="seoul")
TypeError: mixed_params() got multiple values for argument 'address'

Parameter 에는 문법적 오류가 없으나, 함수 호출부분에서 문제가 되었다. "address"가 keyword argument 인 "address"에서 한 번, 마지막의 **kwargs 에 한 번 더 전달되면서 오류가 난 것으로 보인다.

함수 호출 부분에서 "address = "seoul"의 값을 삭제하고 Positional arguments - keyword arguments 순으로 배치하였더니 아래와 같은 결과가 나타 난다.

def mixed_params(age, address, name="아이유", *args, **kwargs):


#순서: Positional arguments 
#-> keyword arguments 
#-> Variable length arguments 
#-> Variable keyword arguments 

    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", "seoul", mobile="01012341234")

#순서: Positional arguments 
#-> keyword arguments

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

아래와 같이 전달되어 함수가 호출되어버렸다.

최종적으로 호출시 arguments 의 순서를 바꾸어주었다.

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

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

Error 가 뜰 때 함수 정의에서 나타난 에러인지, 함수 호출에서 나타난 에러인지 확인하고 이에 맞게 parameters 와 arguments 의 순서를 공부했다.

끝!!

0개의 댓글