티스토리 뷰

728x90
반응형

파이썬에서 언팩킹과 팩킹

zip()의 파라미터는 1개가 될 수도 있고, 2개가 될 수도, 10개가 될 수도 있다. 밑의 실험을 보면 알 수 있다.

>>> a = ['a1', 'a2']
>>> b = ['b1', 'b2']
>>> c = ['c1', 'c2']
>>> d = ['d1', 'd2']
>>> list(zip(a))
[('a1',), ('a2',)]
>>>list(zip(a, b))
[('a1', 'b1'), ('a2', 'b2')]
>>> list(zip(a, b, c))
[('a1', 'b1', 'c1'), ('a2', 'b2', 'c2')]

여기에는 아스테리스크(Asterisk) 혹은 흔히 별표라고 부르는 *를 활용한다. 파이썬에서 *는 언팩(Unpack)이다. 시퀀스 언패킹 연산자(Sequence Unpacking Operator)로 말 그대로 시퀀스를 풀어 헤치는 연산자를 뜻하며, 주로 튜플이나 리스트를 언패킹하는 데 사용한다. 밑의 예를 보자.

>>> import collections
>>> nums = [1, 1, 1, 2, 2, 3]
>>> k = 2
>>> collections.Counter(nums).most_common(k)
[(1, 3), (2, 2)]
>>> list(zip(*collections.Counter(nums).most_commons(k)))
[(1, 2), (3, 2)]
>>> list(zip(collections.Counter(nums).most_commons(k)))
[((1, 3),), ((2, 2),)]

입력값이 [1, 1, 1, 2, 2, 3]일 때 collections.Counter(nums).most_common(k)의 결과는 [(1, 3), (2, 2)]이다. 그러나 이 값을 그대로 zip()으로 묶어 보면 엉뚱한 결과가 나온다. [((1, 3),), ((2, 2),)] 이런 식으로 튜플이 풀어지지 않고 그대로 하나으 ㅣ값처럼 묶여 버렸다. 이 경우 *로 언팩킹을 해줘야 튜플의 값을 헤칠 수 있다. 언패킹한 값만 별도로 출력할 수가 없기 때문에 디버깅이 어렵지만, 아마 내부적으로는 튜플이 제거되고 [[1, 3], [2, 2]]과 같은 형태로 모두 리스트로 풀어질 것이다. 이제 이 값을 zip()으로 묶으면 정상적으로 묶이게 된다. 간단한 예를 하나 더 살펴보자.

>>> fruits = ['lemon', 'pear', 'watermelon', 'tomato']
>>> fruits
['lemon', 'peer', 'watermelon', 'tomato']

fruits라는 리스트를 출력하면 당연히 리스트 형태로 출력된다. 만약 이 리스트에서 각 요소의 값만 출력하고 싶다면 어떻게 될까? 이때 *로 언패킹을 해주면 다음과 같이 매우 간편하게 출력할 수 있다.

>>> print(*fruits)
lemon pear watermelon tomato

이외에도 *는 활용도가 많다. 언패킹뿐만 아니라 함수의 파라미터가 되었을 때는 반대로 패킹도 가능하다. 맨 처음에 언급했던 zip()에 파라미터를 여러 개 쓸 수 있다는 얘기 또한 내부적으로 zip() 함수 정의에서 *로 패킹하고 있다는 얘기이기도 하다.

>>> def f(*params):
...     print(params)
...
>>> f('a', 'b', 'c')
('a', 'b', 'c')

이처럼 하나의 파라미터를 받는 함수에 3개의 파라미터를 전달했지만, params 변수 하나로 패킹되어 처리된다. 이는 파이썬 3+에서 print() 함수의 기본 동작 원리이기도 하다.

다음과 같이 또 다른 활용 예를 살펴보자.

>>> a, *b = [1, 2, 3, 4]
>>> a
1
>>> b
[2, 3, 4]
>>> *a, b = [1, 2, 3, 4]
>>> a 
[1, 2, 3]
>>> b
4

변수의 할당 또한 이렇게 *로 묶어서 처리할 수 있다. 일반적인 변수는 값을 하나만 취하지만 *로 처리하게 되면 나머지 모든 값을 취하게 된다. 마지막으로 하나가 아닌 2개를 쓰는 경우도 있다. ** 2개는 다음과 같이 키/값 페어를 언패킹하는 데 사용된다.

>>> date_info = {'year': '2020', 'month': '01', 'day': '7'}
>>> new_info = {**date_info, 'day': "14"}
>>> new_info
{'year': '2020', 'month': '01', 'day': '14'}

이처럼 **date_info에 모든 요소를 언패킹할 수 있으며, 여기서는 'day': "14"의 새로운 값으로 업데이트도 시도했다. 그 결과 값은 변경된 것을 확인 할 수 있다.



출처

파이썬 알고리즘 인터뷰 (글 : 박상길 그림 : 정진호) [책만]

728x90
반응형
댓글
반응형
250x250
글 보관함
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Total
Today
Yesterday
링크