Python-Function Paramters

강현구·2021년 12월 2일
0

Python

목록 보기
13/21

Function Paramters

함수는 input parameter를 받아서 정의된 내용대로 parameter를 연산하고 output값을 return한다.
다시말해, 함수를 호출할 때는 parameter를 함수에 건내주며(pass) 호출한다.

positional argument

가장 기본적인 형태로 입력된 순서대로 값이 parameter로 함수에 전달된다.
반드시 함수를 정의할 때 맞춰진 순서대로 전달해줘야 하며, 맞지 않는 값이 전달되면 호출에서 error가 발생한다.
positional arguments

keyword Arguments

함수를 정의할 때의 순서대로 넣지 않고, 매개변수 이름을 keyword로 값을 전달하는 방법도 가능하다.
keyword = 값의 형태로 값을 전달해주면 되고, 순서는 상관없다.
이렇게 keyword를 사용하면 가독성이 높아지고 코드 관리가 상대적으로 수월하다.
keyword arguments

positional + keyword

위의 두가지 방법을 섞어서 쓰는 방법도 가능하다.
단, 이때 positional arg'는 순서를 지켜주어야한다.
(keyword arg'는 상관없다.)
mix of them

Default Value

함수의 parameter에 default값을 정의해 줄 수도 있다.
default값이 있으면 함수 호출 시에 값이 전달되지 않아도 된다.

만약, default값이 정의된 parameter가 정의되지 않은 것보다 먼저 위치해서는 안된다.
default값이 정의된 parameter가 먼저 나올 경우 syntax error가 발생한다.

def love_you(my_name = "정우성", your_name): 
    print(f"{my_name} loves {your_name}") 
   
> Traceback (most recent call last):   
    File "python", line 1 
SyntaxError: non-default argument follows default argument

Complex Function Paramters

위의 매개변수 입력 방식에 한단계 더 활용 가능한 방식들이 있다.

Unknown number of arguments

함수에 입력되는 매개변수가 적고, 숫자가 고정적이라면 위의 방식을 사용하면 되겠지만 그렇지 않은 경우에는 다른 방법이 필요하다.

def buy_A_car(options):
    print(f"다음 사양의 자동차를 구입하십니다:")

    for option in options:
        print(f"{option} : {options[option]}")

options = {"seat" : "가죽", "blackbox" : "최신"}

buy_A_car(options)

> 다음 사양의 자동차를 구입하십니다:
seat : 가죽
blackbox : 최신

이럴 경우에 사용할 수 있는 방법 중, dictionary를 parameter로 받아서 사용하는 방법이 있다.
아래와 같이 만들면 원하는 숫자만큼(함수에서 정의된 매개변수의 개수 제약없이) 사용할 수 있다.
하지만 이 경우에는 값을 dictionary로 받아야하고 매개변수가 없을 때에도 빈 dictionary라도 넘겨주어야 한다.
사용에 다소 불편함이 있다.

Keyworded variable length of arguments

그래서 이러한 불편함을 해결하며 사용할수 있는 방법이 있다.
바로 매개변수의 앞에 별표**를 붙이는 방법이다.
이렇게 정의한 매개변수는 일반적인 keyword arguments처럼 사용하면 된다.
keyword arguments와의 차이점은

  • argument를 0~N개까지 유동적으로 넘길 수 있다.
  • keyword가 미리 정해져 있지 않기 때문에 원하는 keyword를 유동적으로 사용할 수 있다.
  • Keyworded variable length of arguments는 dictionary 타입으로 지정된다.

일반적으로 Keyworded variable length of arguments의 이름은 **kwargs로 정한다.
함수 내부에서는 kwargs로 전달된 값을 kwargs라는 이름에 할당된 dictionary 처럼 사용하면 된다.
keyworded variable length of arguments

Non-keyworded variable length of arguments

이 방식은 Keyworded variable length of arguments와 동일하지만 keyword를 사용하지 않는다.
variable arguments라고 하기도 한다.
variable arguments를 선언하는 방법은 별표*를 한개만 사용해서 선언하면 된다.
variable arguments는 tuple로 지정되어 함수에 전달된다.
non-keyworded variable length of arguments

Mix!!

위 방법도 섞어서 (*args, **kwargs)와 같이 사용할 수 있다
이 경우에는 어떠한 형태의 값에도 전달 가능한 함수가 된다.
parameter에 있어서 유동적인 함수를 만들 수 있다.

do_something(1, 2, 3, name="정우성", age=45)
do_something(1, 2, 3, 4, 5, "hello", {"주소" : "서울", "국가" : "한국"})
do_something(name="정우성", gender="남", height="187")
do_something(1)
do_something()

Think about

  1. 함수를 정의 할때 default value parameter를 non-default value parameter 앞에 정의 하면 안 되는 이유

다음과 같은 함수를 만들었다.(원래는 오류가 나겠지만,)

def today(year=2021, month, day=2): 
    print(f"오늘은 {year}{month}{day}일 입니다.")

today(2019,21)

함수를 호출하면서 입력한 201921은 어디에 입력되야 하는 것일까.
사람은 당연히 2019year21day에 들어갈 것이라는 것을 알지만, 컴퓨터는 그렇지 않다.
값을 순서대로 넣으면 될지, 아니면 default값이 없는 매개변수부터 넣을지 이러한 기준도 없고 모호한 표현이 되기 때문에 컴퓨터 입장에서는 함수를 제대로 호출할 수 없는 상황이 발생한다. 이런 상황 때문에 값이 없더라도 사용할 수 있는 매개변수를 뒤로 정의하고 값을 입력해줘야 하는 매개변수를 앞에 쓰도록 정했다고 볼 수 있다.

컴퓨터는 모호한 것을 싫어한다.

  1. 위치 인수(positional arguments)와 가변 인수(variable length arguments)의 위치
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 "test.py", line 6, in <module>
    func_param_with_var_args("정우성", "01012341234", "seoul", 20)
TypeError: func_param_with_var_args() missing 1 required keyword-only argument: 'age'

가변인수가 두번째 값부터 전부 전달받으면서 age parameter에 전달되는 값이 없어서 발생한 에러이다.

풀이 1)
함수의 가변인수를 가장 뒤로 보내준다.
대신 이때는 입력되는 값도 순서를 바꿔주어야한다.
(아마도,, 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("정우성", 20, "01012341234", "seoul")

풀이 2)
입력되는 값에서 keyword를 사용해서 지정해준다.
함수에서 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("정우성", "01012341234", "seoul", age = 20)

두 풀이 모두 아래의 결과를 얻을 수 있다.

#결과
name=정우성
args=('01012341234', 'seoul')
age=20
  1. 가변 키워드 인수 (variable length keyword arguments)의 위치
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")

  File "test.py", line 1
    def func_param_with_kwargs(name, age, **kwargs, address=0):
                                                    ^^^^^^^
SyntaxError: invalid syntax

문법 오류가 발생한다. 애초에 default지정 매개변수를 keyword 가변인수 뒤에 쓰는 것 자체가 불가능하다.

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("정우성", "20", mobile="01012341234", address="seoul")

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

default지정 매개변수를 keyword 가변인수 앞에서 정의해준다.
default값 대신 keyword로 전달된 값이 출력되고 나머지 값들은 kwargs로 전달됨을 알 수 있다.

  1. 위치 인수와 키워드 가변 키워드 인수 (variable length keyword arguments)의 위치를 위치
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")

  File "test.py", line 1
    def mixed_params(name="아이유", *args, age, **kwargs, address):
                                                        ^^^^^^^
SyntaxError: invalid syntax

앞서의 3번과 마찬가지로 문법 오류가 발생한다, 3번과 같이 우선 **kwargs를 가장 마지막 변수로 정의한다.
추가로 매개변수 age도 앞의 2번과 같은 형태가 되어있으므로 위치를 바꿔준다.

def mixed_params(age, name="아이유", *args, 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)

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

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

결과가 제대로 출력된다.
풀이 중 이 문제에서 실수한 것이 있는데, 첫번째 때 함수의 매개변수를 다음과 같이 순서를 바꿨다.

def mixed_params(age, address, name="아이유", *args, **kwargs):
#이하 생략.

  File "test.py", line 8, in <module>
    mixed_params(20, "정우성", "01012341234", "male" ,mobile="01012341234", address="seoul")
TypeError: mixed_params() got multiple values for argument 'address'

가변인수를 전부 뒤로 보내주었을 때는 address에서 문제가 발생한다.
함수에서 address를 전부 지워주니, 실행이 가능하고 대신 함수를 호출하면서 addresskeyword로 입력한 값도 kwargs에 같이 들어간다.
첫번째 시도때 했던 순서로 정의할 경우에 address변수에 여러개의 값이 충돌되는 것으로 보인다.


Summary

파이썬에서는 매개변수를 순서에따라 처리하고 있고 그 순서는 다음과 같다.

  1. positional(non-default) arguments
  2. default arguments
  3. variable length positional arguments (=*arg)
  4. keyword-only arguments
    4-1. non-default keyword-only arguments
    4-2. default keyword-only arguments
  5. variable length keyword arguments (=**kwargs)

특히나 keyword로 전달되는 값의 경우 실수할 가능성이 높으니 함수 정의에 참고하자.


foo(x) # a=x, b=3, args=(), kwargs={}
foo(x, y) # a=x, b=y, args=(), kwargs={}
foo(x, b=y) # a=x, b=y, args=(), kwargs={}
foo(x, y, z, k) # a=x, b=y, args=(z, k), kwargs={}
foo(x, c=y, d=k) # a=x, b=3, args=(), kwargs={'c': y, 'd': k}
foo(x, c=y, b=z, d=k) # a=x, b=z, args=(), kwargs={'c': y, 'd': k}

추가 공부할 사이트 링크

profile
한걸음씩

0개의 댓글