본문 바로가기
C.W.K.
Stream
Lesson 03 of 07 · published

itertools — 반복을 조립하는 표준 도구

~25 min · itertools, chain, groupby, tee, product

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

무한 반복자는 반드시 끝 조건과 짝지어

count, cycle, repeat는 스스로 끝나지 않아. islice, 조건, 유한 소비자처럼 멈추는 장치와 함께 써야 해.

이어 붙이고 길이를 맞추고 일부만 고르기

chain은 여러 반복값을 하나로 잇고, zip_longest는 짧은 쪽의 빈자리를 채우며, islice는 리스트를 만들지 않고 구간만 소비해.

groupby는 붙어 있는 값만 묶는다

groupby는 같은 키가 연속될 때만 한 그룹으로 묶어. SQL처럼 같은 키를 모두 합치려면 먼저 그 키로 정렬해야 해. 각 그룹도 원본 반복자를 공유하므로 필요할 때 바로 소비해.

조합과 복제

product는 데카르트 곱, permutations는 순서 있는 배열, combinations는 순서 없는 선택을 만들어. tee는 한 반복자를 여러 갈래로 나누지만 갈래의 속도가 다르면 내부 저장량이 커질 수 있어.

Code

무한 반복자에 끝 조건 붙이기·python
import itertools as it

# count — range 인데 무한
for n in it.count(10, 2):
    if n > 20:
        break
    print(n)              # 10 12 14 16 18 20

# cycle — 라운드로빈
colors = it.cycle(["red", "green", "blue"])
for _ in range(7):
    print(next(colors))
# red green blue red green blue red

# repeat — 제한 또는 무한
print(list(it.repeat("x", 4)))    # ['x', 'x', 'x', 'x']

# 무한 zip + 유한 list
pairs = list(zip(it.count(1), ["a", "b", "c"]))
print(pairs)                       # [(1, 'a'), (2, 'b'), (3, 'c')]
chain·zip_longest·islice로 흐름 바꾸기·python
import itertools as it

# chain — iterable 이어붙임
result = list(it.chain([1, 2], [3, 4], [5]))
print(result)                      # [1, 2, 3, 4, 5]

# zip_longest — 가장 짧은 거에서 안 멈춤
result = list(it.zip_longest([1, 2, 3], ["a", "b"], fillvalue="?"))
print(result)                      # [(1, 'a'), (2, 'b'), (3, '?')]

# islice — *모든* iterable 슬라이싱, 무한 포함
def naturals():
    n = 1
    while True:
        yield n
        n += 1

first_5 = list(it.islice(naturals(), 5))
print(first_5)                     # [1, 2, 3, 4, 5]
연속된 키만 묶는 groupby·python
import itertools as it

items = ["apple", "ant", "banana", "berry", "apricot"]

# 순진한 groupby — 연속 매치만 그룹
for key, group in it.groupby(items, key=lambda x: x[0]):
    print(key, list(group))
# a ['apple', 'ant']
# b ['banana', 'berry']
# a ['apricot']               <- 두 번째 'a' 그룹, 합쳐지지 *않음*

# SQL 스타일 그룹핑은 정렬 먼저
items.sort(key=lambda x: x[0])
for key, group in it.groupby(items, key=lambda x: x[0]):
    print(key, list(group))
# a ['apple', 'ant', 'apricot']
# b ['banana', 'berry']
곱·순열·조합 만들기·python
import itertools as it

# product — 데카르트 곱 (nested for 루프 대체)
for x, y in it.product([1, 2], ["a", "b"]):
    print(x, y)
# 1 a
# 1 b
# 2 a
# 2 b

# permutations — 모든 순서 있는 배치
print(list(it.permutations("abc", 2)))
# [('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')]

# combinations — 순서 없는 선택
print(list(it.combinations("abc", 2)))
# [('a', 'b'), ('a', 'c'), ('b', 'c')]

# combinations_with_replacement — 재사용 가능한 선택
print(list(it.combinations_with_replacement("ab", 2)))
# [('a', 'a'), ('a', 'b'), ('b', 'b')]
한 반복자를 여러 갈래로 나누는 tee·python
import itertools as it

source = (x*x for x in range(5))
a, b, c = it.tee(source, 3)

print(list(a))               # [0, 1, 4, 9, 16]
print(list(b))               # [0, 1, 4, 9, 16]
print(list(c))               # [0, 1, 4, 9, 16]

# 주의 — tee() 후에는 원본 source를 다시 쓰지 마
# tee 버퍼에 들어감

# 대부분 경우 list 로 materialize 하는 게 더 명확
squares = [x*x for x in range(5)]

External links

Exercise

주어진 events를 user로 정렬한 뒤 itertools.groupby로 {user: [actions...]}를 만들어. 이어서 users와 ['red', 'green', 'blue']의 모든 짝을 product로 만들고, 무한 count()에 islice를 적용해 [10, 13, 16, 19, 22]를 얻어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인 — 댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.