함수를 사용할때는 인자의 순서에 따라 값을 넣어야한다.
def personal_info(name, age, address):
print('이름: ', name)
print('나이: ', age)
print('주소: ', address)
personal_info('홍길동', 30, '서울시 용산구 이촌동')
그렇다면 키워드 인자를 사용해서 작성한다면?
personal_info(age=30, address='서울시 용산구 이촌동', name='홍길동')
순서를 지키지 않아도 키워드에 해당하는 값이 들어간다.
만약 매개변수에서 초기값이 지정되어있다면?
def personal_info(name, age, address='비공개'):
print('이름: ', name)
print('나이: ', age)
print('주소: ', address)
personal_info('홍길동', 30)
# 이름: 홍길동
# 나이: 30
# 주소: 비공개
초기값을 지정한 경우에 해당 값을 생략하고 호출한 경우 초기값이 리턴되고,
personal_info('홍길동', 30, '서울시 용산구 이촌동')
# 이름: 홍길동
# 나이: 30
# 주소: 서울시 용산구 이촌동
초기값이 지정되어 있더라도 값을 넣으면 해당 값이 전달된다.
단, 초기값이 지정된 매개변수 다음에는 초기값이 없는 매개변수가 올 수 없다. 즉
def personal_info(name, address='비공개', age): #SyntaxError: non-default argument follows default argument
print('이름: ', name)
print('나이: ', age)
print('주소: ', address)
위와 같은 경우에는 에러가 발생하니, 초기값이 지정된 매개변수는 맨 뒤에 몰아주도록 하자.
def func(*args):
print(args)
print(type(args))
func(1, 2, 3, 4, 5, 6, 'a', 'b')
#(1, 2, 3, 4, 5, 6, 'a', 'b')
#<class 'tuple'>
이 때 *args는 함수로 전달된 인자들을 튜플로 묶어준다.
즉 func(1, 2, 3, 4, 5, 6, 'a', 'b')를 호출하면, args 변수는 위와 같이 튜플로 구성된다.
def sum_all(*numbers):
result = 0
for number in numbers:
result += number
return result
print(sum_all(1, 2, 3, 4, 5, 6)) # 21
packing을 이용해 반드시 받아야하는 매개변수와, 여러개를 받을 수 있는 매개변수를 분리해서 작성할 수 있다.
def print_family_name(father, mother, *sibling):
print("아버지 :", father)
print("어머니 :", mother)
if sibling:
print("호적 메이트..")
for name in sibling:
print(name)
print_family_name("홍길동", '심사임당', '김태희', '윤아')
아버지 : 홍길동
어머니 : 심사임당
호적 메이트..
김태희
윤아
계속 예시를 보자.
exam1,exam2,exam3 = "DB", "OS", "JAVA"
def cal(*exams):
for exam in exams:
print(exam)
cal(exam1,exam2,exam3)
# DB
# OS
# JAVA
exam1,exam2,exam3 = "DB", "OS", "JAVA"
def cal(date, *exams):
print(date)
for exam in exams:
print(exam)
cal("4/17", exam1,exam2,exam3)
# 4/17
# DB
# OS
# JAVA
단, 이 때 가변인자는 일반 변수 뒤에 있어야한다.
즉 def cal(*exams.date):
은 에러.
def kwpacking(**kwargs):
print(kwargs)
print(type(kwargs))
kwpacking(a=1, b=2, c=3)
{'a': 1, 'b': 2, 'c': 3}
<class 'dict'>
def print_family_name(father, mother, **sibling):
print("아버지 :", father)
print("어머니 :", mother)
if sibling:
print("호적 메이트..")
for title, name in sibling.items():
print('{} : {}'.format(title, name))
print_family_name("홍길동", '심사임당', 누나='김태희', 여동생='윤아')
아버지 : 홍길동
어머니 : 심사임당
호적 메이트..
누나 : 김태희
여동생 : 윤아
이 때 가변 인자와 키워드 인자 패킹을 동시에 사용할 수도 있다.
def print_family_name(*parents, **sibling):
print("아버지 :", parents[0])
print("어머니 :", parents[1])
if sibling:
print("호적 메이트..")
for title, name in sibling.items():
print('{} : {}'.format(title, name))
print_family_name("홍길동", '심사임당', 누나='김태희', 여동생='윤아')
def sum(a, b, c):
return a + b + c
numbers = [1, 2, 3]
# sum(numbers) # error
print(sum(*numbers)) #6
[1, 2, 3]을 인자로 보낼때, *을 붙이면 unpacking이 발생한다.
당연하지만 함수의 매개변수의 개수와 인자의 개수가 다를 떄는 에러가 발생한다.
def sum(a, b, c):
return a + b + c
numbers = [1, 2, 3, 4]
print(sum(*numbers)) #TypeError: sum() takes 3 positional arguments but 4 were given
def sum(a, b, c):
return a + b + c
print(sum(*'123')) #123
print(sum(*'ABC')) #ABC
print(sum(*'가나다')) #가나다
print(sum(*'가','나','다')) #가나다
print(sum(*{'가':1, '나':2, '다':3})) #가나다
def cal(first, op, second):
if op == '+':
return first + second
if op == '/':
return first / second
if op == '-':
return first - second
if op == '*':
return first * second
prob = {
'first': 12,
'second': 34,
'op': '*'
}
cal(**prob) # 결과 : 408
사실 우리는 이미 이 예시를 자주 사용했다. 대표적인 것이 print이다.
print("출력값", end = " ")
등 출력값을 가변인자로, end나 sep을 키워드 인자로 넣어 사용했었다.
def simple_function(a, b, *args, **kwargs):
print(f"a: {a}, b: {b}")
print(f"args: {args}")
print(f"kwargs: {kwargs}")
simple_function(1, 2, 3, 4, 5, x=10, y=20)
# a: 1, b: 2
# args: (3, 4, 5)
# kwargs: {'x': 10, 'y': 20}
여담이지만 실수를 했는데
def custom_print(*args, **kwargs):
print(*args, **kwargs)
user_input = input("Enter something: ")
custom_print(user_input, end=" ", sep=":")
Enter something: 123a
123a
의도한 결과는 1:2:3:a이었는데, 위와 같이 나왔다.
이유는 sep을 사용하기 위해 입력된 문자열을 분리해서 전달해야하기 때문이다.
(위의 입력값 자체가 하나의 값이기 때문)
그러므로 다음과 같이 수정한다.
def custom_print(*args, **kwargs):
print(*args, **kwargs)
user_input = input("Enter something: ")
custom_print(*user_input, end=" ", sep=":")
단, 이때 def custom_print(**kwargs, *args)
처럼
**kwargs
가 *args
보다 앞쪽에 오면 안 된다.
매개변수 순서에서 **kwargs
는 반드시 가장 뒤쪽에 와야 한다.
특히 고정 매개변수와 *args, **kwargs
를 함께 사용한다면
def custom_print(a, b, *args, **kwargs):
처럼 매개변수는 고정 매개변수, *args, **kwargs 순으로 지정해야 한다.
REFERENCE