*args
영어로 하면 variable length arguments
conventional하게 *args
라고 쓸뿐이지, *alex
, *apple
, *ant
뭐라고 쓰든 자유다
복수의 일반 인자를 사용자에게 입력받아서 사용할 때 쓰인다
(정확히는, 정해지지 않은 수의 일반 인자)
--> 여러개의 인자를 받은 경우, 함수 내부에서는 튜플로 받은 것처럼 인식한다.
이 *args
를 사용할 때는 주의할 점이 몇 가지 있다
다음의 코드를 보자
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 "/Users/soomialexhwang/Desktop/rfsd.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'
이게 왜 에러가 났냐하면, 함수 선언부에 그 이유가 있다.
*args
는 사용자가 몇 개의 인수를 입력할지 모르는 상황, 즉 여러 개의 인수를 입력받을 수도 있는 경우에 사용한다고 하였다
요 바로 직전 포스팅에서 적었듯 이 함수는 첫 선언 시 파라미터 정의에 민감하다
내 생각에 기본 형식을 벗어나는 파라미터 정의는 무조건 마지막에 나오는 것이 맞다
에러를 맞지 않으려면 다음과 같이 정의하는 것이 좋다
def func_param_with_var_args(name, age, *args):
print("name=",end=""), print(name)
print("age=",end=""), print(age)
print("args=",end=""), print(args)
func_param_with_var_args("정우성", "01012341234", "seoul", 20)
age와 args가 순서가 바뀌어있다.
그리고 이렇게 실행하면?
name=정우성
age=01012341234
args=('seoul', 20)
로 잘 실행되는 것을 볼 수 있다.
**kwargs
영어로 하면 keyword arguments
역시, conventional하게 *kwargs
라고 쓸뿐이지, *kite
, *kitten
, *king
뭐라고 쓰든 자유다
*args
와 다른 점이라면, **kwargs
는 키워드로 이루어진 복수의 인자를 받는다
(정확히는, 정해지지 않은 수의 키워드로 이루어진 인자)
자 다음의 코드를 보고 왜 안되는 지 생각해보자
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")
이 코드는 실행이 아예 되지 않는다 (Invalid Syntax)
어떻게 해야 실행이 될 수 있을까 고민해보았다.
**kwargs
같은 특수 인자 역시, 위에서*args
에서처럼 맨 뒤에 위치해야 하는 것 아닐까?
그래서 코드에서 address와 자리를 바꾸어서 다시 실행했다
>>>
name=정우성
age=20
kwargs={'mobile': '01012341234'}
address=seoul
잘 출력되었다!
(참고로 함수 정의 시, address=0이라는 파라미터가 영 이상해서, address만으로도 실행해보았는데 결과는 똑같이 출력되었다.)
*args
와 **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")
솔직히 조금 예상했는데, 실제로 IDLE에서 실행 자체가 되지 않았다 (Invalid Syntax)
예상한 문제점
1.*args
뒤에 일반 인자인 age가 있다
2.**kwargs
뒤에 일반 인자인 address가 있다
3. 게다가 name="아이유"는 Default 인자! --> 맨 앞에서 정의되어서는 안된다고 했다
4. 근데 여기서 잠깐!
*args
와**kwargs
, default인자의 서열은 어떻게 처리하지?
사실 그냥 느낌대로 IDLE을 한 번 돌려보고 싶어서 우선은
age, address, *args
와 **kwargs
, default인자 순서로
파라미터를 지정한 후, 코드를 실행시켰다.
실행 결과는 역시 Invalid Syntax 에러!
그럼 이번엔 조금 바꾸어서
age, address, default인자,*args
와 **kwargs
순서로
실행
Traceback (most recent call last):
File "/Users/soomialexhwang/Desktop/rfsd.py", line 19, in <module>
mixed_params(20, "정우성", "01012341234", "male" ,mobile="01012341234", address="seoul")
TypeError: mixed_params() got multiple values for argument 'address'
실행은 되는데 에러가 나온다
근데 에러 내용을 조금 읽어보니,
앗차 알겠구나 address가 이미 default값으로 지정되었는데 파라미터로 또 지정한 것이다!
함수 지정시의 파라미터 순서만 너무 신경쓰느라,
막상 함수에 투입되는 파라미터를 보지 않았다
함수에 투입되는 파라미터를 다시 바로 잡을 필요가 있어 보여서 코드를 수정했다
def mixed_params(age, address, name="아이유", *args, **kwargs):
print("age=",end=""), print(age)
print("address=",end=""), print(address)
print("name=",end=""), print(name)
print("args=",end=""), print(args)
print("kwargs=",end=""), print(kwargs)
mixed_params(20, address="seoul", "정우성", "01012341234", "male" ,mobile="01012341234")
이번엔 될 줄 알았다 솔직히
근데
내가 못보고 넘어가는게 있나? 싶어서 다시 한 번 원래 코드로 돌아가서 찬찬히 보며 분석했다
다시 한 번 이 코드의 문제점을 찾자
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")
- 가변인자
*args
가 일반인자age
,address
보다 뒤에 위치해있다- 키워드 가변인자
**kwargs
도 다소 앞에 위치해있다.name="아이유"
는 디폴트값 인자인데 맨 앞에 있다. 디폴트값 인자는 맨 뒤에 위치한다.- 근데, 여기서 하나 더 보이는게 생겼다
address에 넣는 인자 값을 보면,
address="seoul"
이라고 쓰고 있는데 이런 인자는 앞에서 본적이 없는데?찾아보니 Keyword-Only arguments라고 부르는 특수 인자값으로
이는*args
보다는 뒤에 위치한다.
아 그럼 다시 짜보자;;
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")
자 마지막이기를 바라며 내가 짠 코드 리뷰해보기
함수 정의 시 순서:
일반 인자 -> default 일반 인자 -> 가변 인자 -> Keyword-Only 인자 -> 키워드 가변 인자
실행 결과는?
나왔다
😭
네시간 싸웠다 ;;;;;
🍎 그렇다면 절대적인 순서와 규칙을 다음의 사진을 보며 다시 한 번 정리
def 함수명( ⭐️ ):
⭐️ 위치에 인자를 정의하는 순서와 규칙
- 일반 positional 인자
- 디폴트 인자 (이미 값을 지정한 인자)
- 가변 인자 (
*args
)- 디폴트가 아닌 Keyword-Only 인자
- 디폴트 Keyword-Only 인자
- 단 4, 5번은 (4, 4', 5, 5')식의 정렬이 아니라 (4, 5, 4', 5') 식으로 정렬
- 가변 키워드 인자 (
**kwargs
)
📖 references
개미님의 브런치 글: https://brunch.co.kr/@princox/180
args와 kwargs 정리해주신 또 다른 분 블로그: https://m.blog.naver.com/PostView.nhn?blogId=wideeyed&logNo=221455090671&proxyReferer=https:%2F%2Fwww.google.com%2F
(당연히) 점프 투 파이썬: https://wikidocs.net/book/1
https://getkt.com/blog/python-keyword-only-arguments/
정리 너무 잘하신거 같아요 감사합니다 !!