[Python] itertools 모듈을 이용해 편리하게 반복자를 만들자

Yewon Choi·2020년 9월 16일
0

Python

목록 보기
25/29

chain, count, izip, imap, islice, tee, cycle, repeat, dropwhile, takewhile, ifilter, groupby

📌 itertools 모듈이란?

ython 에서 제공하는 자신만의 반복자를 만드는 모듈

📌 패키지 임포트

import itertools

📌 chain()

리스트( lists/tuples/iterables ) 를 연결

letters = ['a', 'b', 'c', 'd', 'e', 'f']
booleans = [1, 0, 1, 0, 0, 1]
decimals = [0.1, 0.7, 0.4, 0.4, 0.5]

print list(itertools.chain(letters, booleans, decimals))

결과 : ['a', 'b', 'c', 'd', 'e', 'f', 1, 0, 1, 0, 0, 1, 0.1, 0.7, 0.4, 0.4, 0.5]

📌 count()

count 는 반복하고자 하는 최대수를 미리 알지 않아도 되는 경우 사용.

from itertools import count , izip
for number, letter in izip(count(0, 10), ['a', 'b', 'c', 'd', 'e']):
    print '{0}: {1}'.format(number, letter)

결과: 0: a 10: b 20: c 30: d 40: e

0 에서 시작해서 10씩 5개의 요소에 대해서 필요한 만큼 증가시킴

유사) 시작과 step 만 있는 range 함수

📌 izip

zip () 함수와 유사하지만, 다른점은 iterable 객체를 반환한다.

from itertools import izip

print list(izip([1, 2, 3], ['a', 'b', 'c']))

결과 : [(1, 'a'), (2, 'b'), (3, 'c')]

📌 imap

map () 함수와 거의 동일한 방식으로 작동

from itertools import imap

print list(imap(lambda x: x * x, xrange(10)))
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

📌 islice

반복가능 객체에서 자르고 싶은 만큼 자를 수 있다.


from itertools import islice

for i in islice(range(10), 5):
    print i

for i in islice(range(100), 0, 100, 10):
    print i

결과 : 0 1 2 3 4
[0 ~ 10] 의 반복가능 객체에서 5번째 안으로 짤라라

결과 : 0 10 20 30 40 50 60 70 80 90
islice () 함수는 slice () 함수와 동일하게 작동
첫 번째 매개 변수는 반복 가능한 객체이고,
두 번째 매개 변수는 시작 색인.
세 번째 매개 변수는 끝 색인
마지막 매개 변수는 각 반복 후에 건너 뛸 수있는 단계 또는 숫자

📌 tee

from itertools import tee

i1, i2, i3 = tee(xrange(10), 3)
print i1
# <itertools.tee object at 0x2a1fc68>
print list(i1)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print list(i1)
# []
print list(i2)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print list(i2)
# []
print list(i3)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print list(i3)
# []

tee () 함수는 두 개의 매개 변수를 사용한다
첫 번째는 반복 가능
두 번째는 만들고자하는 복사본 개수

한번 사용된 레퍼런스는 더 이상 값을 참조 하지 않는다.


r = (x for x in range(10) if x < 6)
print r
# <generator object <genexpr> at 0x2a22870>
i1, i2, i3 = tee(r, 3)
print list(r)
# [0, 1, 2, 3, 4, 5]
print list(i1)
# []
print list(i2)
# []
print list(i3)
# []

이렇게 원본의 제네레이터인 r 을 실행시키면 나머지 복제본들도 다 참조가 끊어진다.

📌 cycle

순환 가능한 객체에서 요소를 반복적으로 생성

from itertools import cycle , izip
for number, letter in izip(cycle(range(2)), ['a', 'b', 'c', 'd', 'e']):
    print '{0}: {1}'.format(number, letter)
    # 0: a
    # 1: b
    # 0: c
    # 1: d
    # 0: e

오른쪽 리스트에 따라 한정지어진다.

📌 repeat

요소를 반복. 반복되는 개수 지정.

from itertools import repeat
print list(repeat('Hello, world!', 3))
# ['Hello, world!', 'Hello, world!', 'Hello, world!']

📌 dropwhile

필터링 함수.
조건에 맞지 않으면, drop
맞으면, 포함시켜 return

from itertools import dropwhile
print list(dropwhile(lambda x: x < 10, [1, 4, 6, 7, 11, 34, 66, 100, 1]))
# [11, 34, 66, 100, 1]

📌 takewhile

필터링 함수
조건에 맞는 값이 나올 때까지 모든 요소 반환

from itertools import takewhile
print list(takewhile(lambda x: x < 10, [1, 4, 6, 7, 11, 34, 66, 100, 1]))
# [1, 4, 6, 7]

📌 ifilter

필터링 함수
조건에 맞는 값을 반환

from itertools import ifilter
print list(ifilter(lambda x: x < 10, [1, 4, 6, 7, 11, 34, 66, 100, 1]))
# [1, 4, 6, 7, 1]

📌 groupby


from operator import itemgetter
from itertools import groupby

attempts = [
    ('dan', 87),
    ('erik', 95),
    ('jason', 79),
    ('erik', 97),
    ('dan', 100)
]

# Sort the list by name for groupby
attempts.sort(key=itemgetter(0))

# Create a dictionary such that name: scores_list
print {key: sorted(map(itemgetter(1), value)) for key, value in groupby(attempts, key=itemgetter(0))}
# {'dan': [87, 100], 'jason': [79], 'erik': [95, 97]}

key 함수로 itemgetter(0) 를 이용하여 정렬후, 첫번째 요소로 groupby 한다. (정렬 해야 한다.)

from collections import defaultdict

counts = defaultdict(list)
attempts = [('dan', 87), ('erik', 95), ('jason', 79), ('erik', 97), ('dan', 100)]

for (name, score) in attempts:
    counts[name].append(score)

print counts
# defaultdict(<type 'list'>, {'dan': [87, 100], 'jason': [79], 'erik': [95, 97]})


defaultdict 사용. 널값에 대한 체크를 생략할 수 있는 편의 를 제공한다.

출처 :
https://www.blog.pythonlibrary.org/2016/04/20/python-201-an-intro-to-itertools/
https://hamait.tistory.com/803

profile
https://github.com/devAon 찰나의 개발흔적을 남기는 개발블로그 입니다 🐥 https://aonee.tistory.com 에서 Velog로 블로그 이전 작업중입니다 ! 🎶

0개의 댓글