함수를 실행할 때 Parameter(이하 매개변수)에 값을 주는 방법에는 여러가지가 존재하고 이를 argument(인수) 라고 하고 가장 기본적인 인수는 두가지가 있다.
각 매개변수의 포지션에 맞게 값을 주면서 호출하는 방법이다
#code
def positionalArgu(a, b):
print('a=',end=""), print(a)
print('b=',end=""), print(b)
#first case
positionalArgu(1,2)
#second case
positionalArgu(1)
#third case
positionalArgu(1,2,3)
#first result
#a=1
#b=2
#second & thrid result
'''
함수를 호출할 때 a와 b에 할당될 값이 알맞게 제공해야하는데
두번째 케이스에서는 b에 들어갈 값이 할당되지 않기 때문에 에러가나고
세번째 케이스는 함수에서 세번째에 들어갈 매개변수가 정의되어 있지않기
때문에 에러가 발생한다.
'''
위와같이 positionalArgu 라는 함수를 호출하면서 해당 함수에 필요한 매개변수(Parameter)에 값을 넘겨줄 때, 즉 a와 b에 각 값을 넣어줄 때 각 매개변수가 위치한 포지션에 알맞게 넣을 값을 적는 방법이다.
각 매개변수의 이름을 키워드로 삼아서 변수를 선언하는 것처럼 값을 넘기는 방법 . 매개변수의 순서와 상관없이 값을 넘길 수 있고 가독성도 좋아진다는 장점이 있다.
def keywordArgu(a, b):
print('a=',end=""), print(a)
print('b=',end=""), print(b)
#first case
keywordArgu(a=1,b=2)
#second case
keywordArgu(b=2,a=1)
#first result
#a=1
#b=2
#second result
#a=1
#b=2
#매개변수의 순서와 상관없이 값을 넘길수 있어서 두가지 케이스 모두 똑같은 결과
위치인수와 키워드 인수는 섞어서 사용할 수 있다. 단, 위치인수를 사용하여 값을 넘기는 부분은 받는 매개변수의 위치를 정확하게 맞춰줘야한다.
def mixPosKey(a,b,c):
print('a=',end=""), print(a)
print('b=',end=""), print(b)
print('c=',end=""), print(c)
#first case
mixPosKey(1,b=2,3)
#second case
mixPosKey(b=2,1,3)
#first result
#a=1
#b=2
#c=3
#second result
'''
두번째 케이스에서 (b=2,1,3) 에 있는 요소들을 순서대로 함수 매개변수에
할당을 해준다고 생각을 해보자
가장 앞에 있는 b=2는 키워드 인수이기 때문에 함수의 b에 2라는 값이 할당되고
1과 3은 위치 인수이기 때문에 함수에서 2번째 3번째 순서에 각각 할당이
되어야하는데 2,3 번째 매개변수인 b,c중에 b는 이미 값이 할당이 되어있다.
그렇게 되어 이미 값이 있는 b에 다시 값을 줄수 없으므로 충돌이 일어나
Syntax error가 발생한다.
'''
위에 두가지 타입의 인수들이 가진 특성을 보면 함수를 호출하면서 값을 넘기고 실행되기까지의 과정을 어느정도 유추할수가 있다. 어떠한 함수를 호출하면서 값을 넘기는 과정에서 넘길 값들을 튜플구조로 묶인 상태로 넘어간다. 튜플 자료구조는 수정이 아예 불가능하도록 설계된 자료구조이기 때문에 위에 mix예제에서 두번째 케이스를 보면 이미 키워드 인수로 b의 값이 먼저 할당된 후, 또다시 b의 값을 수정할 수 없기 때문에 신텍스 에러가 발생하는 것 같다.
함수의 매개변수에 기본(default)값을 정의해 줄 수 도 있다. 기본값이 정의된 매개변수는 함수가 호출 할때 값을 넘기지 않아도 된다. 값을 넘기지 않은 경우 이전에 설정되어있던 기본값이 자동으로 넘겨지게 된다.
def defaultVal(a, b=2):
print('a=',end=""), print(a)
print('b=',end=""), print(b)
defaultVal(1)
#result
#a=1
#b=2
앞서말한 키워드 인수와 위치인수를 섞을 때 순서에 주의해야 했던 것 처럼 default value parameter와 non-default value parameter를 하나의 함수 안에서 사용할 때 default value parameter의 위치가 non-default value parameter의 위치보다 앞에 있으면 안된다는 것이다 (Syntax error).
그렇다면 왜 안되는 걸까?
함수를 호출 할 때 인수들을 튜플로 묶어서 정의된 함수의 매개변수 튜플과 비교하며 올바르게 매개변수에 값을 전달할 수 있는지 판단 후 실행한다.
그렇다면 두가지의 튜플을 내부적으로 비교를 하면서 모든 매개변수에 한번씩만 값이 할당이 된다면 함수가 정상적으로 작동이 될 수 있다. (뇌피셜1 참조)
그렇다면 다시 기본값을 주는 매개변수가 왜 그렇지않은 매개변수보다 앞에 있으면 안되는 것일까 고민을 해보았다.
머릿속에서 나온 결론은, 인수들을 묶어서 튜플을 보내는 과정에서 디폴트값을 선언해준 매개변수가 있으면 그것들을 가장 튜플의 오른쪽 인덱스로 키워드인수값으로 처리해서 묶어버리는게 아닐까 하는 생각이든다.
가변인수란, 영어에 적혀있는 말 그대로 길이가 변할 수 있는 인수를 뜻한다.
즉, 여러가지의 인수들을 할당 할 수 있다는 얘기다.
가변인수를 사용할 때 주의할 점은 매개변수를 선언하면서, 가변인수를 받을 매개변수의 위치가 일반인수(위치인수 || 키워드인수)를 받을 매개변수의 위치보다 뒤에 있어야한다. (디폴트 값 매개변수 와 같은 규칙)
기본적인 사용 예시를 한번 보자.
def func_param_with_var_args(name, age, *args):
print("name=",end=""), print(name)
print("age=",end=""), print(age)
args.push('abc')
print("args=",end=""), print(args)
print("args[0]=",end=""), print(args[0])
print("args[1]=",end=""), print(args[1])
func_param_with_var_args("정우성", 20, "01012341234", "seoul")
#result
# name=정우성
# age=20
# args=('01012341234', 'seoul')
# args[0]=01012341234
# args[1]=seoul
################## 잘못된 사용 예시 #####################
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)
'''
이렇게 되면 ('01012341234', 'seoul', 20) 이라는 값이 튜플형으로
args매개변수에 한번에 들어가기 때문에 age 매개변수에 값을 할당할 수가
없어서 에러가 발생한다.
'''
가변 키워드 인수는 가변인수에서 키워드를 붙여 dictionary형의 자료를 넘기게 해주는 인수다.
쉽게 설명하자면 가장 처음에 적은 위치인수와 키워드인수가 가변인수안에서 설정이 되는 느낌이다.
주의할 점은, 가변 키워드 인수에 넣을 key="value" 형의 값을 넣을 때 key값이 이미 함수에 있는 매개변수의 이름과 겹치면 안된다.
#잘못된 예
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", address="busan")
#result
'''
Traceback (most recent call last):
File "python", line -
SyntaxError: keyword argument repeated
'''
#올바른 예
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", address2="busan")
#result
'''
name=정우성
age=20
address=seoul
kwargs={'mobile': '01012341234', 'address2': 'busan'}
'''
가변인수와 가변 키워드 인수를 함께 쓰게 될 함수를 정의할 때와 호출할 때 조금 복잡한 규칙이 있는데,
예시를 살펴보자
#잘못된 예
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")
#result
'''
Traceback (most recent call last):
File "python", line -
def mixed_params(name="아이유", *args, age, **kwargs, address):
^
SyntaxError: invalid syntax
'''
#올바른 예
def mixed_params(age, name="아이유", *args, address, **kwargs):
print("age=",end=""), print(age)
print("name=",end=""), print(name)
print("args=",end=""), print(args)
print("address=",end=""), print(address)
print("kwargs=",end=""), print(kwargs)
mixed_params(20, "아이", "정우성", "01012341234", "male", address="seoul" ,mobile="01012341234")
#result
'''
age=20
name=아이
args=('정우성', '01012341234', 'male')
address=seoul
kwargs={'mobile': '01012341234'}
'''
#함수를 호출할 때 어떤 인수로 넘겨주는지 주의해서 보면 이해가 될 것이다.