늒네 기록

[python] unzip()함수는 없을까? 본문

언어 공부 기록/python

[python] unzip()함수는 없을까?

jaeha lee 2020. 10. 9. 21:19

2020/10/09 - [언어 공부 기록/python] - [python] zip() 함수에 대하여 글에서 iterable한 객체들이 주어져있고 이 객체들이 들고 있는 아이템을 순서대로 묶고싶을 때 zip() 함수를 쓰면 된다고 했다. 그렇다면, 딱 이 과정을 역방향으로 진행해주는 unzip 함수는 없을까? 예를 들어, 아래와 같은 상황이라고 하자.

1
2
3
4
5
6
7
8
9
10
= [123]
= ['a''b''c']
= ['foo''bar''baz']
 
= zip(a, b, c)
 
print(y) # <zip object at 0x00D47E88>
print(list(y)) # [(1, 'a', 'foo'), (2, 'b', 'bar'), (3, 'c', 'baz')]
 
aa, bb, cc = unzip(y) #...?
cs

10번째 줄에 있는 unzip을 하면, aa, bb, cc는 각각 a, b, c가 들고있는 것과 같은 아이템을 들고있도록 하는 것이 우리가 원하는 것이다.

 

답은 의외로 간단하다. zip() 함수가 했던 것이 무엇인지 생각해보면,

- 변수로 받은 iterable한 객체를 받아서,

- 각 객체에 들어있는 아이템을 순서대로 하나로 묶어주었다.

 

그런데 위의 코드에서 a, b, c를 zip으로 묶은 객체가 들고 있는 아이템들을 가지고 다시 생각해보면,

- zip 함수로 묶고 나면 각 객체는 (a의 아이템, b의 아이템, c의 아이템) 순서로 구성되어 있다.

- 그런데 우리가 원하는 것은 a는 a끼리, b는 b끼리, c는 c끼리 묶어주는 것이다.

- 그렇다면 zip함수로 묶인 객체의 첫 번째 아이템을 찾아서 묶어주고, 두 번째 아이템을 찾아서 묶어주고, 세 번째 아이템을 찾아서 묶어주면 되는 것 아닌가?

 

즉, zip을 해서 나온 오브젝트의 내용물을 가지고 다시 한 번 zip을 하면 원하는 결과물을 얻을 수 있을 것이다. 앞서 작성한 zip 관련 포스팅에서 객체의 내용물만 전달하는 방법으로 *를 쓰면 된다는 것을 보았다. 이를 활용하여 실제로 코드를 작성하고 실행해보면 다음과 같은 결과를 얻을 수 있다.

1
2
3
4
5
6
7
8
= [1234]
= ['a''b''c''d''e']
= ['foo''bar''baz']
 
= zip(a, b, c)
 
print(y) # <zip object at 0x00D47E88>
print(list(zip(*y))) # [(1, 2, 3), ('a', 'b', 'c'), ('foo', 'bar', 'baz')]
cs

여기서 눈여겨볼만한 건, zip함수가 a, b, c중 짧은 객체를 기준으로 아이템들을 묶어주었기 때문에, 묶인 아이템을 다시 zip 함수로 풀면서 짧은 객체 기준으로 결과물이 잘려나가있으며, 결과물이 tuple 타입으로 묶여있다.

리스트 형태로 결과물을 받고 싶으면 다음과 같이 간단한 수정을 하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
= [1234]
= ['a''b''c''d''e']
= ['foo''bar''baz']
 
= zip(a, b, c)
 
print(y) # <zip object at 0x00D47E88>
aa, bb, cc = [list(l) for l in zip(*y)]
 
print(aa) # [1, 2, 3]
print(bb) # ['a', 'b', 'c']
print(cc) # ['foo', 'bar', 'baz']
cs

그리고 한 가지 더 유의할 점은, 아래와 같은 방식으로 코드를 짜면 작동하지 않는다는 점이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
= [1234]
= ['a''b''c''d''e']
= ['foo''bar''baz']
 
= zip(a, b, c)
 
print(y) # <zip object at 0x00D47E88>
print(list(y)) # [(1, 'a', 'foo'), (2, 'b', 'bar'), (3, 'c', 'baz')]
 
aa, bb, cc = zip(*y)
'''
Traceback (most recent call last):
  File "cf.py", line 10, in <module>
    aa, bb, cc = zip(*y)
ValueError: not enough values to unpack (expected 3, got 0)
'''
# print(aa, bb, cc)
cs

zip(*y)를 실행하고 난 결과물을 aa, bb, cc에 넣어주어야 해서 결과물의 아이템이 3개가 필요한데, 실제로는 0개가 있다는 ValueError가 발생한다. 왜 이런 걸까? 이는 다음 글에 이어서 알아보도록 하겠다.

2020/10/09 - [언어 공부 기록/python] - [python] zip() 함수에 대하여 - 2

반응형
Comments