[Python] - packing, unpacking

김진수·2020년 11월 30일
1
post-thumbnail
post-custom-banner

packing

print함수는 출력하고자하는 객체가 몇개던지, 즉 몇개의 인자를 받던지 상관하지 않고 출력해줍니다. 이런 경우처럼 함수가 받을 인자의 갯수를 유연하게 지정할 수 있다면 보다 유연하게 코드를 작성할 수 있습니다.

파이썬은 이런 경우를 지원하기 위해 packing을 지원합니다.

패킹은 인자로 받은 여러개의 값을 하나의 객체로 합쳐서 받을 수 있도록 합니다.

위치인자 패킹은 *한개를 매개변수 앞에 붙임으로 사용합니다.

def func(*args):
      print(args)
      print(type(args))
      
func(1, 2, 3, 4, 5, 6, 'a', 'b')


-result-
(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

-result-
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("홍길동", '심사임당', '김태희', '윤아')

-result-
아버지 : 홍길동
어머니 : 심사임당
호적 메이트..
김태희
윤아

위치인자가 패킹하는 매개변수를 만나면 그 이후에 위치인자가 몇개이던지, tuple로 하나의 객체가되어서 관리됩니다.

def kwpacking(**kwargs):
     print(kwargs)
     print(type(kwargs)

kwpacking(a=1, b=2, c=3)

-result-
{'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("홍길동", '심사임당', 누나='김태희', 여동생='윤아')

-result-
아버지 : 홍길동
어머니 : 심사임당
호적 메이트..
누나 : 김태희
여동생 : 윤아

위치 인자와 키워드 인자 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을 할때는, 매개변수에서 을 붙이는게 아니라 인자 앞에 을 붙여서 사용합니다.

def sum(a, b, c):
    return a + b + c

numbers = [1, 2, 3]

print(sum(*numbers)) 

-result-
6

[1, 2, 3]을 인자로 보낼때, *을 붙이면 unpacking이 발생합니다.

unpacking은 아래와 같은 순서로 변경되어 실행됩니다.

  • sum(*numbers)
  • sum(*[1, 2, 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) 

-result-
408
profile
백엔드 개발자
post-custom-banner

0개의 댓글