반응형

 python에서 zip 함수는 유용하게 쓰일 수 있는 메서드 중 하나입니다. 어떻게 쓰이는지 간단하게 예제를 보겠습니다.

 

 


 zip 메서드에 대한 설명을 보면, Iterable한 것을 여러개 받게끔 되어 있습니다. 뭐가 뭔지 모르겠으니, 설명에서 예제로 나온 것 부터 해석해 보도록 하겠습니다. list(zip('abcdefg', range(3), range(4)))를 보시면, iterable한 것이 3개나 들어왔음을 알 수 있어요. str, 범위, 범위 이렇게요.

 

 그런데, 결과가 [('a', 0, 0), ('b', 1, 1), ('c', 2, 2)]가 최종적으로 나왔습니다. 여기서 유추할 수 있는 것 하나는, zip 메서드가 병렬적으로 iterator를 돌림을 알 수 있습니다.

 

 

 'abcdefg', range(3), range(4)가 있습니다. 이들에 대해서 각각 iterator를 돌린다고 해 보겠습니다. 처음에 각각의 이터들은 'a', 0, 0을 가리킬 겁니다. 다음 next는 'b', 1, 1을 가리키고 있습니다. 다음으로 이동해 보겠습니다.

 

 

 3개의 iterable한 객체에 대해서 병렬적으로 다음 원소로 이동하였습니다. 그러면 'b', 1, 1로 이동할 겁니다.

 

 

  또 다시 다음 원소로 이동하게 되면, 'c', 2, 2로 이동하게 됩니다. 각 단계별로 제가 색칠한 것들은 iter를 돌리면서 취합된 결과물입니다. 이것과, 문서에서 설명된 결과물이 일치합니다. 대략 어떤 일을 하는지 눈치를 채셨으리라 생각합니다. 한 마디로 병렬적으로 이터를 돌려서 결과를 취하기 위해 쓴다 정도로 생각하시면 됩니다.

 


 이제 어떻게 쓰일 수 있는지 하나의 예제를 여러 단계로 쪼개면서 이해해 보도록 하겠습니다.

 

 

 먼저, 해당 프로그램의 결과가 어떻게 나올까요? 일단 3개의 list가 있고, 각각의 것들은 iterable 합니다. 그러므로, 병렬적으로 이 셋에 대해서 iterator를 돌려버린 것을 취합하면 <5, 3, 1>과 <6, 4, 2>가 나올 겁니다.

 

 

 음. 실제 결과는 셋에 대해서 iterator를 돌린 결과가 취합되어서 tuple로 리턴되는 듯 싶네요. 우리는 이것을 list로 리턴되게끔 바꾸고 싶습니다. 그리고, 이 결과들을 list에 저장하고 싶어요. 즉, [[5, 3, 1], [6, 4, 2]] 이런 식으로 저장하고 싶습니다. 아래와 같이 쓰시면 됩니다.

 

 

 zip을 순회하면서 받은 결과들이 있습니다. (5, 3, 1)과 (6, 4, 2)입니다. 이들을 list로 변환하면 [5, 3, 1], [6, 4, 2]입니다. 이들로 구성된 list인 board를 생성하겠다는 의미입니다.

 

 

 결과는 위와 같습니다. 이것을 왜 굳이 제가 언급했을까요? 사실 이것은 [[1, 2], [3, 4], [5, 6]]을 오른쪽으로 90도 굴린 결과입니다. 배열 회전을 구현할 때 zip 메서드를 이용하면 매우 간단하게 구현할 수 있다는 의미입니다. 단지, [5, 6], [3, 4], [1, 2]를 인자 [5, 6], [3, 4], [1, 2]로 푸는 방법만 안다면요.

 

 board가 [[5, 6], [3, 4], [1, 2]]라면, 이 board는 객체 [5, 6], [3, 4], [1, 2]를 가지고 있어요. 이들을 풀어주는 것을 unpacking이라 해요. 앞에다가 *를 붙이면 됩니다.

 

 

 그러면, 회전하는 방법도 이해가 될 겁니다. 단지, 우리는 board[::-1]에 unpacking을 한 결과를 zip에 넘겨주면 됩니다. for loop가 1번 돌아갔을 때, *board[::-1]은 [5, 6] [3, 4] [1, 2]로 언패킹이 될 겁니다. 이것을 zip에 넣으면 인자로 [5, 6], [3, 4], [1, 2]를 받게 됩니다. 그러면 1번 for loop 안에 있는 내용들이 실행되었을 때 오른쪽으로 90도 돌아간 결과가 board에 반영되게 됩니다.

 

 

 실행 결과는 위와 같습니다.

반응형

댓글을 달아 주세요