또 다른 반복문인 iteratools와 comprehension에 대해 정리합니다.

개요


  • python의 주요 기능인 iteration모듈의 개념과 활용방법에 대한 내용을 정리합니다.

itertools 모듈

itertools 모듈 : 다양한 종류의 iterator(반복하는 것) 객체를 생성하는 함수들로 구성된 모듈

  • product(), combination(), permutations() 3가지 함수로 구성되어 있다.

itertools.product(*L)

  • 순회 가능한 여러개의 객체를 순서대로 순회하는 iterator를 생성하는 함수
1
2
3
for v1, v2, v3 in itertools.product(L1, L2, L3): 

와 같은 식으로 작성한다.

이는 아래의 for 문과 동일한 구조이다.

1
2
3
4
5
6
7
for v1 in L1:

    for v2 in L2:

        for v3 in L3:

1
import itertools
1
2
3
4
# itertools.product 예제
count = 0
for a, b, c in itertools.product(range(5), range(5), range(5)):
    print(a, b, c) # 각각의 for문이 도는 결과를 표시
0 0 0
0 0 1
0 0 2
0 0 3
0 0 4
0 1 0
0 1 1
0 1 2
0 1 3
...
4 3 3
4 3 4
4 4 0
4 4 1
4 4 2
4 4 3
4 4 4
1
2
3
4
5
# 위 코드와 같은 방식으로 동작하는 코드
for a in range(5):
    for b in range(5):
        for c in range(5):
            print(a, b, c)
0 0 0
0 0 1
0 0 2
0 0 3
0 0 4
0 1 0
0 1 1
0 1 2
...
4 4 1
4 4 2
4 4 3
4 4 4

즉, product() 함수는 nested for문의 깊이가 매우 깊을때 유용하게 사용된다.

zip 함수와 itertools.product 함수의 차이

1
2
for a, b, c in zip(range(5), range(5), range(5)):
    print(a, b, c)
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
  • zip() 안에 포함된 요소들이 ‘대등’하게 적용된다.

  • a가 0~5범위에서 for문을 돌때,b와c도 동일한 범주에서 반복문을 수행한다.

itertools.combination(p,r)

  • iterator 객체 p에서 크기 r의 가능한 모든 조합을 갖는 iterator를 생성하는 함수
1
2
3
L = ['a', 'b', 'c', 'd']
for comb in itertools.combinations(L, 2): # L에서 2개로 이뤄진 가능한 모든 조합 뽑기
    print(comb)
('a', 'b')
('a', 'c')
('a', 'd')
('b', 'c')
('b', 'd')
('c', 'd')
1
2
3
4
5
# L에서 출력 가능한 모든 조합을 뽑으려면

for r in range(1, len(L) + 1): # L 전체 범위를 돌아야 하기 때문에 +1
    for comb in itertools.combinations(L, r):
        print(comb)
('a',)
('b',)
('c',)
('d',)
('a', 'b')
('a', 'c')
('a', 'd')
('b', 'c')
('b', 'd')
('c', 'd')
('a', 'b', 'c')
('a', 'b', 'd')
('a', 'c', 'd')
('b', 'c', 'd')
('a', 'b', 'c', 'd')

itertools.permutations(p,r)

  • iterator 객체 p에서 크기 r의 가능한 모든 순열을 갖는 iterator를 생성하는 함수
1
2
3
4
# L에서 가능한 모든 순열 뽑기
for r in range(1, len(L)):
    for comb in itertools.permutations(L, r):
        print(comb)
('a',)
('b',)
('c',)
('d',)
('a', 'b')
('a', 'c')
('a', 'd')
('b', 'a')
('b', 'c')
('b', 'd')
('c', 'a')
('c', 'b')
('c', 'd')
('d', 'a')
('d', 'b')
('d', 'c')
('a', 'b', 'c')
('a', 'b', 'd')
('a', 'c', 'b')
('a', 'c', 'd')
('a', 'd', 'b')
('a', 'd', 'c')
('b', 'a', 'c')
('b', 'a', 'd')
('b', 'c', 'a')
('b', 'c', 'd')
('b', 'd', 'a')
('b', 'd', 'c')
('c', 'a', 'b')
('c', 'a', 'd')
('c', 'b', 'a')
('c', 'b', 'd')
('c', 'd', 'a')
('c', 'd', 'b')
('d', 'a', 'b')
('d', 'a', 'c')
('d', 'b', 'a')
('d', 'b', 'c')
('d', 'c', 'a')
('d', 'c', 'b')

List comprehension

  • comprehension은 for문을 한 줄로 작성해 리스트를 효과적으로 생성하는 방법이다.

  • 조건문은 생략 가능하다.

1
2
3
[output for element in iterator if 조건] 

의 형태로 작성된다.

e.g)

1
2
3
L = [x**2 for x in range(10) if x%2 ==0] 

이는 아래의 for문과 동일한 의미이다.

1
2
3
4
5
6
7
8
9
L=[]

for x in range(10):

    if x%2 == 0

        L.append(x**2)

즉, 코드 작성시 여러줄이 필요한 것을 1줄로 깔끔하게 정리할 수 있다.

기본 comprehension

1
2
L1 = [x for x in range(10)]
L1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1
2
3
4
5
6
7
# 위의 comprehension을 다시 쓰면 다음과 같다.
# 실제로 결과도 같다.

L1 = []
for x in range(10):
    L1.append(x)
L1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

연산이 추가된 comprehension

1
2
L2 = [x**2 for x in range(10)]
L2
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
1
2
3
4
5
6
7
# 위의 comprehension을 다시 쓰면 다음과 같다.
# 실제로 결과도 같다.

L2 = []
for x in range(10):
    L2.append(x**2)
L2    
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

조건문이 붙은 comprehension

1
2
L3 = [x**2 for x in range(10) if x%2 == 0]
L3
[0, 4, 16, 36, 64]
1
2
3
4
5
6
7
8
# 위의 comprehension을 다시 쓰면 다음과 같다.
# 실제로 결과도 같다.

L3 = []
for x in range(10):
    if x%2 == 0:
        L3.append(x**2)
L3
[0, 4, 16, 36, 64]
1
2
3
4
5
X = [1, 2, 3, 'a', 'b']
Y = [3, 1, 2, 'c', 4]

L4 = [x + y for x, y in itertools.product(X, Y) if type(x) == type(y) == int]
L4
[4, 2, 3, 5, 5, 3, 4, 6, 6, 4, 5, 7]

dictionary comprehension

  • comprehension은 for문을 한 줄로 작성해 사전을 효과적으로 생성하는 방법이다.
1
2
3
{key:value for key, val in iterator if 조건}

의 형태로 작성된다.

e.g)

1
2
3
dic = {x:y**2 for x,y in zip(range(10), range(10)) if x%2 ==0}

이는 아래의 for문과 동일한 의미이다.

1
2
3
4
5
6
7
8
9
10
11
dic = dict()



for x,y in zip(range(10), range(10)):

    if x%2 == 0:

        dic[x] = y**2

x를 key로, y를 value로 하는 사전을 생성

즉, 코드 작성시 여러줄이 필요한 것을 1줄로 깔끔하게 정리할 수 있다.

기본 comprehension

1
2
dic1 = {x:y for x, y in zip(range(10), range(10))}
dic1
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
1
2
3
4
5
6
7
# 위의 comprehension을 다시 쓰면 다음과 같다.
# 실제로 결과도 같다.

dic1 = dict()
for x,y in zip(range(10),range(10)):
    dic1[x] = y
dic1    
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}

dict의 NaN값을 items()를 활용해 채워넣기

  • 이전에 정리한 바와 같이 dict 자료형은 items()함수를 이용하여 tuple형태로 key, value 순회 가능하다.

  • items() 사용법은 사전.items() 로 변형하여 tuple의 unpacking개념을 이용해 다수의 값을 한번에 대입하는 방식이다.

1
dic = {1:'NaN', 2:2, 3:4, 4:'NaN'}
1
2
3
4
# y! = NaN이면 그 값을 dict에 추가

dic2 = {x:y for x, y in dic.items() if y != 'NaN'}
dic2
{2: 2, 3: 4}
1
2
3
4
5
6
7
8
9
# 위의 comprehension을 다시 쓰면 다음과 같다.
# 실제로 결과도 같다.

dic2 = dict() #빈 dict 정의

for x, y in dic.items(): # dict의 item을 loop
    if y != 'NaN': 
        dic2[x] = y
dic2        
{2: 2, 3: 4}

댓글남기기