packing, unpacking
print
함수는 출력하고자하는 객체가 몇개던지, 즉 몇개의 인자를 받던지 상관하지 않고 출력해줍니다.
print("가나다 abc 123")
print("가나다", "abc 123")
print("가나다", "abc", "123")
출력결과
가나다 abc 123
가나다 abc 123
가나다 abc 123
이런 경우처럼 함수가 받을 인자의 갯수를 유연하게 지정할 수 있다면 보다 유연하게 코드를 작성할 수 있습니다.
파이썬은 이런 경우를 지원하기 위해 packing
을 지원합니다.
패킹은 인자로 받은 여러개의 값을 하나의 객체로 합쳐서 받을 수 있도록 합니다.
위치인자 패킹은 *
한개를 매개변수 앞에 붙임으로 사용합니다.
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'>
이러한 packing을 통해 받은 모든 숫자들의 합을 구하는 연산도 구할 수 있습니다. 몇개든 상관없이 가능합니다.
def sum_all(*numbers):
result = 0
for number in numbers:
result += number
return result
print(sum_all(1, 2, 3)) # 6
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("홍길동", '심사임당', '김태희', '윤아')
결과값
아버지 : 홍길동
어머니 : 심사임당
호적 메이트..
김태희
윤아
위치인자가 패킹하는 매개변수를 만나면 그 이후에 위치인자가 몇개이던지, tuple로 하나의 객체가되어서 관리됩니다.
동일하게 키워드 인자에 패킹은 **
을 통해 작성할 수 있습니다.
def kwpacking(**kwargs):
print(kwargs)
print(type(kwargs)
kwpacking(a=1, b=2, c=3)
결과값
{'a': 1, 'b': 2, 'c': 3}
<class 'dict'>
키워드 인자는 패킹한 인자들을 키워드와 인자 쌍으로 이뤄진 딕셔너리로 관리합니다.
이를 이용해서 print_family_name
함수에 호적메이트들에 사회적명칭도 출력하도록 변경할 수 있습니다.
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("홍길동", '심사임당', 누나='김태희', 여동생='윤아')
결과값
아버지 : 홍길동
어머니 : 심사임당
호적 메이트..
누나 : 김태희
여동생 : 윤아
위치 인자와 키워드 인자 packing
을 동시에 사용할 수 있습니다.
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("홍길동", '심사임당', 누나='김태희', 여동생='윤아')
unpacking
packing
과 반대되는 개념인 unpacking
이라는 개념이 있습니다.
packing
은 여러개의 객체를 하나의 객체로 합쳐주었습니다. unpacking
은 여러개의 객체를 포함하고 있는 하나의 객체를 풀어줍니다.
함수에서 unpacking
을 할때는, 매개변수에서 *
을 붙이는게 아니라 인자 앞에 *
을 붙여서 사용합니다.
동일하게 위치인자를 unpacking 하는 경우는
*
를, 키워드인자를 unpacking하는 경우**
를 사용합니다.
def sum(a, b, c):
return a + b + c
numbers = [1, 2, 3]
sum(numbers) # error
print(sum(*numbers)) # 출력 : 6
[1, 2, 3]
을 인자로 보낼때, *
을 붙이면 unpacking
이 발생합니다.
unpacking은 아래와 같은 순서로 변경되어 실행됩니다.
1. sum(*numbers)
2. sum(*[1, 2, 3])
3. sum(1, 2, 3)
unpacking
은 함수를 호출할때 인자를 해체하는 개념이기 때문에, 해채된 결과가 함수의 매개변수에 갯수와 다르다면 에러가 발생합니다.
sum(*[1, 2, 3, 4])
실행결과
TypeError: sum() takes 3 positional arguments but 4 were given
위치인자를 unpacking
할때는 위에 예에서는 list
타입이였지만, Container
객체라면 다 가능합니다.
sum(*'abc') # 'abc'
sum(*(4, 5, 6)) # 15
sum(*{'가', '나', '다'}) # '나다가'
sum(*{'치킨': 3, '피자': 12, '음료수': 10}) # '치킨피자음료수'
set
타입과dict
타입은 순서정보를 가지고 있지 않기 때문에 결과가 다를 수 있습니다.
동일한 방식으로 키워드인자로 unpacking
할 수 있습니다. unpacking하기 위해선 인자가 key
와 인자
로 구성되어 있는 mapping
타입, 즉 dict
가 필요합니다.
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
위 예제에 키워드 인자의 unpacking
은 다음과 같이 작동합니다.
1. cal(**prob)
2. cal(prob = {
'first': 12,
'second': 34,
'op': '*'
})
3. cal(first=12, second=34, op='*')
위치인자의 unpacking
처럼 unpacking
되는 인자는 매개변수의 키워드 매개변수와 일치해야합니다.
만약 비어있는 인자를 unpacking
를 하면 무시합니다. 이러한 특성이 있기 때문에 함수의 packing
과 unpacking
을 이용하여, 다음과 같이 어떠한 함수에도 반응하는 함수를 작성할 수 있습니다.
함수와 함수에 인자들을 받아서 시작전 알림과 함께 함수를 실행시켜주는 함수입니다.
def start(func, *args, **kwargs):
print("함수를 시작합니다.")
return func(*args, **kwargs)
실행할 함수를 인자로 받고, 그 함수를 실행할때 넣을 위치인자와 키워드인자를 갯수와 상관없이 넣어줍니다.
start(print, '안녕하세요', '파이썬 꿀잼!', sep='~~ ')
실행결과
함수를 시작합니다.
안녕하세요~~ 파이썬 꿀잼!
def sum_a_b(a, b): return a + b result = start(sum_a_b, 1, 2) # 함수를 시작합니다. print(result) # 3
'C Lang > Python Basic' 카테고리의 다른 글
클로저 사용하기1 - 변수의 사용 범위 알아보기: 전역범위, 지역범위, 네임스페이스, global 키워드 (0) | 2019.11.06 |
---|---|
mutable과 immutable 객체, shallow copy, deep copy (0) | 2019.11.01 |
네임스페이스란, 네임스페이스의 종류, 네임스페이스가 생성된 배경, 자바스크립트의 블록스코프와의 비교 (0) | 2019.10.28 |
python에서 custom exception 개발하고 사용하기 (0) | 2019.09.27 |
deep dive in python super() method (0) | 2019.09.25 |