2.12. 루프

루프 는 같은 코드 블록을 반복해서 실행합니다. Python에는 두 가지 형태가 있습니다. 조건이 참인 동안 계속 진행하는 while 과, 시퀀스의 항목들을 순회하는 for 입니다.

나란히 놓인 순서도. while: 조건을 검사하고, 참이면 본문을 실행한 뒤 반복한다. for: 이터러블에서 다음 항목을 꺼내 본문을 실행하고, 소진될 때까지 반복한다.

while 은 조건을 계속 검사하고, for 는 시퀀스가 소진될 때까지 순회합니다.

2.12.1. while 루프

while 루프는 각 반복 전에 조건을 검사하고, 검사가 거짓이 될 때까지 본문을 실행합니다:

count = 0
while count < 5:
    print(count)
    count += 1

출력:

0
1
2
3
4

조건이 처음에 참이고 결코 거짓이 되지 않으면 루프는 영원히 실행됩니다. while True: 는 메인 루프의 표준 관용구로, break 로 명시적으로 빠져나옵니다:

while True:
    step()
    if done():
        break

2.12.2. for 루프

for 루프는 이터러블의 항목들을 순회합니다 – 리스트, 튜플, 문자열, 바이트, 딕셔너리, 또는 반복을 지원하는 그 밖의 무엇이든 가능합니다:

for fruit in ["apple", "banana", "cherry"]:
    print(fruit)

출력:

apple
banana
cherry

같은 형태가 문자열에서도 동작하며, 이때 각 항목은 한 글자짜리 문자열입니다:

for letter in "OpenMV":
    print(letter)

출력:

O
p
e
n
M
V

딕셔너리를 직접 순회하면 삽입 순서대로 키가 나옵니다:

for key in {"a": 1, "b": 2}:
    print(key)

출력:

a
b

각 차례마다 루프 변수(fruit, letter, key)가 다음 항목에 바인딩됩니다. 루프가 끝난 뒤에도 변수는 마지막 반복의 값을 유지합니다.

2.12.3. range

숫자 범위에 대한 for 루프에는 range() 를 사용합니다:

  • range(stop) – 0, 1, …, stop - 1.

  • range(start, stop) – start, start + 1, …, stop - 1.

  • range(start, stop, step) – 사용자 지정 스텝으로(음수 값은 거꾸로 셉니다).

for i in range(5):           # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 8, 2):     # 2, 4, 6
    print(i)

for i in range(10, 0, -1):   # 10, 9, ..., 1
    print(i)

range() 는 값을 지연 생성합니다 – 메모리에 리스트를 만들지 않습니다. 실제 list 를 얻으려면 감싸십시오: list(range(10)).

2.12.4. enumerate

루프에서 인덱스와 항목이 모두 필요할 때는 enumerate()(index, item) 쌍을 내놓습니다:

for i, name in enumerate(["a", "b", "c"]):
    print(i, name)
# 0 a
# 1 b
# 2 c

두 번째 인수를 전달하면 인덱스를 0이 아닌 다른 값에서 시작할 수 있습니다: enumerate(items, start=1).

2.12.5. zip

두 개(또는 그 이상)의 이터러블을 동시에 순회하려면 zip() 을 사용합니다. 위치마다 튜플 하나를 내놓고 가장 짧은 입력에서 멈춥니다:

names  = ["alice", "bob", "carol"]
scores = [88, 92, 70]

for name, score in zip(names, scores):
    print(name, score)

출력:

alice 88
bob 92
carol 70

2.12.6. :=를 사용한 인라인 할당

월러스(walrus) 연산자 := 는 표현식이기도 한 할당입니다. 이름을 바인딩하면서 동시에 같은 값으로 평가됩니다. while 루프에서 이것은 흔한 “읽고, 검사하고, 본문” 패턴을 한 줄로 압축합니다:

# without walrus
value = next_value()
while value is not None:
    process(value)
    value = next_value()

# with walrus
while (value := next_value()) is not None:
    process(value)

두 형태는 같은 일을 합니다. 할당의 중복이 정말로 가독성을 해칠 때 := 를 활용하십시오. 단지 영리해 보이려고 사용하지는 마십시오. 표현식의 모호함을 없애기 위해 대부분의 위치에서 괄호가 필요합니다.