6.2.1 반복: 여러 번 실행하기

반복이란 같은 작업을 여러 번 실행하는 것이다. 매일 아침 7시에 전화벨 울리기, 영화표 구매가 가능한지 5분마다 확인하기, 숫자를 세다가 3, 6, 9가 나오면 박수 치기… 이런 반복 작업은 힘도 들고 실수하기도 쉽다. 하지만 컴퓨터는 몇 번이든 정확하게 해낼 수 있다. 우리가 할 일은 컴퓨터가 정확하게 반복 작업을 수행할 수 있도록 프로그램을 만드는 것 뿐이다. 그렇다면 반복하는 프로그램은 어떻게 만들 수 있을까?

반복 작업을 프로그래밍하는 방법

숫자를 1부터 4까지 차례대로 화면에 출력하는 프로그램을 작성해 보자.

코드 6-16 1부터 4까지 출력하는 프로그램 1

print(1)
print(2)
print(3)
print(4)

이 프로그램은 실행 결과만 보면 제 몫을 한다. 하지만 적절한 프로그래밍 방법은 아니다. 두 가지 문제를 꼽을 수 있는데, 첫 번째는 매 반복 단계에서 수를 바꾸는 계산을 프로그래머가 했다는 것이다. 계산할 식이 더 복잡해지거나 반복해야 할 횟수가 많아지면 프로그래머가 실수할 우려가 크다. 컴퓨터가 더 잘 할 일을 사람이 대신해야 한다면 좋은 프로그램이라고 하기 어렵다.

두 번째 문제는 이 프로그램이 ‘작업의 반복’이 아니라 ‘작업들’을 지시한다는 점이다. “네 번 하시오.”가 아니라 “하시오. 하시오. 하시오. 하시오.”라고 지시하는 것이다. 반복할 횟수가 많아질수록 프로그래머가 작성해야 할 ‘하시오’ 코드도 많아질 것이다. 게다가 몇 번이나 반복해야 할지 미리 알 수 없는 경우에는 이 방법을 아예 쓸 수 없다.

이 문제를 하나씩 해결하며, 반복 작업을 우아하게 지시하는 방법을 알아 보자.

6.2.2 반복의 한 주기를 온전히 나타내기

반복 작업을 프로그래밍할 때는 전체 반복을 생각하기보다 반복의 ‘한 주기’에서 일어나는 일이 무엇인지 생각해야 한다. 한 주기를 정확하게 수행해 내는 것이 핵심이고, 그 주기를 몇 번 반복할 것인지는 부차적이다.

코드 6-17 코드 6-16의 한 주기

print(1)

위 코드는 코드 6-16의 전체 반복에서 한 주기만 떼어낸 것이다. 이 코드를 보고 한 주기에서 일어나는 일이 무엇인지 잘 생각해 보자. 화면에 수를 출력하는 print() 함수가 있다. 그것 뿐일까? 출력해야 할 수, 1은 어떻게 구한 것일까? 코드에는 나와 있지 않지만, 프로그래머가 수를 이전 주기에서 1 만큼 증가시켜 구한 것이다. 즉, 한 주기에서 수행하는 일은 수를 1 증가시키는 것과 그 수를 화면에 출력하는 것 두 가지다. 프로그래머가 대신한 작업을 코드에 추가하여 반복의 한 주기를 온전하게 나타내면 다음과 같다.

코드 6-18 온전히 표현한 한 단계의 작업

number += 1     # 수를 1 증가시킨다
print(number)   # 수를 출력한다

프로그래머가 대신했던 일을 컴퓨터에게 알려줌으로써, 한 행이었던 코드가 두 행으로 늘어났다. 코드가 늘어나긴 했지만 프로그래머의 수고가 줄어들었다. 이로써 반복 횟수가 많아지더라도 프로그래머가 고생하거나 계산이 틀릴 우려가 없어졌다.

다음은 각 반복 주기를 온전하게 나타내도록 프로그램을 수정한 것이다.

코드 6-19 1부터 4까지 출력하는 프로그램 2

number = 0      # 수를 세기 위해 변수가 필요하다

number += 1     # 수를 1 증가시킨다
print(number)   # 수를 출력한다
number += 1
print(number)
number += 1
print(number)
number += 1
print(number)

실행 결과:

1
2
3
4

이제 프로그램에 수를 직접 계산해 넣지 않아도 된다. 이로써 앞서 지적한 문제점 중 첫번째 문제를 해결했다. 하지만 똑같은 코드를 여러 번 반복하여 입력해야 하는 두번째 문제는 여전히 남아 있다. 한 주기에 해당되는 코드 number += 1print(numer)만 작성하고, ‘이걸 네 번 실행하시오’하고 지시할 수 있다면 편리할 것이다.

개념 정리

  • 반복 코드를 작성할 때는 반복의 한 주기를 온전히 파악하고 작성하는 것이 중요하다.

6.2.3 while 문: 조건이 유지되는 동안 반복하기

while 문은 지정한 조건이 유지되는 동안 코드를 계속 반복하는 명령이다. while 문은 기능이 단순해서 사용하기 다소 불편할 때도 있지만, 특별한 제약 없이 다양한 반복 처리를 수행할 수 있다. while 문을 작성하는 양식은 다음과 같다.

while 조건:   # ❶ 첫 행
    본문      # ❷ 조건이 참인 동안 반복 실행할 코드 블록

while 문의 양식은 if 문의 양식과 유사하다. while 문은 if 문처럼 지정된 조건이 참일 때만 본문을 실행한다. while 문과 if 문의 차이는 본문의 코드가 실행되는 횟수다. if 문은 본문을 최대 한 번만 실행하지만, while 문은 조건이 참으로 유지되는 동안에는 몇 번이든 조건 검사와 코드 실행을 반복한다. 영어 단어 ‘while’은 “… 인 동안”이라는 뜻이고, while 문을 우리 말로 옮기면 “조건이 유지되는 동안 본문의 코드를 반복 실행하라”라는 뜻으로 풀이할 수 있다.

반복 횟수 관리하기

while 문은 조건을 확인하고 코드를 실행하는 것을 반복할 뿐이다. 확인하는 조건에 변화가 생기지 않는다면 반복은 영원히 계속될 것이다. 반복을 어떻게 유지하고 어떻게 끝낼지는 프로그래머가 직접 설계해야 한다. 예를 들어, 코드를 N번 반복하도록 하려면 변수를 이용해 반복 횟수를 관리해야 한다. while 문을 이용해 ‘안녕’을 세 번 출력하는 프로그램을 작성하고 실행해 보자.

코드 6-20 ‘안녕’을 세 번 출력하기 (while_1.py)

i = 0              # ❶ 현재 반복된 횟수를 기억하기 위한 변수

while i < 3:       # ❷ 조건(i < 3)이 유지되는 동안 본문을 반복 실행하라
    print('안녕')  # ❸ 화면에 텍스트를 출력하라 (반복을 통해 수행하려는 일)
    i += 1         # ❹ 반복된 횟수가 한 번 증가한 것을 기억하기

실행 결과:

안녕
안녕
안녕

while 문을 다룰 때 반복 흐름을 잘못 설계하거나 조건을 틀리게 입력하면 코드가 무한히 반복 실행될 수 있다. 이번 절의 코드를 따라 입력하다가 오타가 나서 이런 상황이 생긴다면, 당황하지 말고 ‘Ctrl + C’ 키 조합을 입력해 프로그램의 실행을 중지하면 된다.

화면에 ‘안녕’이 세 번 출력되었으면 첫 while 문을 성공적으로 작성한 것이다. 반복 코드를 잘 작성하려면 반복 과정을 한 단계씩 추적해보는 연습을 해야 한다. 다음은 코드 6-20이 실행되는 과정을 한 단계씩 풀어 설명한 것이다. 어렵지 않으니 코드와 비교해가며 차근차근 읽어보도록 하자.

  1. while 문을 시작하기 전, while 문이 반복 실행된 횟수를 기억하기 위해 ❶에서 변수 i를 정의하였다. ‘i’라는 이름은 반복 횟수를 가리키는 변수에 흔히 사용하는 이름이다. 이 시점에서는 아직 반복 주기가 실행되지 않았으므로 0을 대입한다.
  2. ❷에서 while 문을 최초로 실행할 차례가 되면 컴퓨터는 while 문의 조건을 검사한다. 이 시점에서 i는 0이고 0은 3보다 작다. 따라서 조건은 참이다. 그러므로 while 문의 본문을 실행한다.
  3. 본문에는 반복 실행하려는 코드 ❸(화면에 텍스트 출력)과 반복을 제어하기 위한 코드 ❹(현재 반복된 횟수를 1 증가)가 있다. 본문이 실행되면 화면에 ‘안녕’이 출력되고 i는 0에서 1 증가하여 1이 된다.
  4. 본문의 실행을 마치면 ❷로 돌아와 조건이 참인지 다시 검사한다. i가 1로 변경되었지만 여전히 3보다 작으므로 조건이 참이다. 본문(❸, ❹)을 한 번 더 실행하여 화면에 ‘안녕’이 한 번 더 출력되고 i는 2가 된다.
  5. 다시 ❷의 조건을 검사한다. i는 2로 여전히 3보다 작다. 본문(❸, ❹)을 한 번 더 실행한다. 화면에 ‘안녕’이 세 번째로 출력되고 i는 3이 된다.
  6. 다시 ❷의 조건을 검사한다. 이 순간 i는 3이어서 3보다 작지 않다. 조건은 거짓이다. 이번에는 while 문의 본문(❸, ❹)을 실행하지 않고, 그냥 다음 차례의 명령으로 넘어간다. 다음 차례의 명령이 없으므로 프로그램은 끝이 난다.

while 문을 사용할 때는 반복을 올바르게 설계하는 데 신경을 써야 한다. 반복을 잘못 설계하면 원하는 원하는 결과를 얻을 수 없다. 위 프로그램에서 조건을 i > 3으로 잘못 지정했다면 ‘안녕’은 한 번도 출력되지 않는다. 반복 횟수를 갱신하는 ❹가 누락된다면 ‘안녕’이 무한히 반복 출력된다.

while 문을 사용하는 패턴에는 여러 가지가 있는데, 지금 살펴본 반복 횟수를 관리하는 패턴이 가장 기본적이다. 코드를 N번 반복 실행 패턴을 다음과 같이 정리하여 두자.

코드를 N번 반복하는 while 문 패턴

  1. 반복을 시작하기 전, 반복 횟수를 기억할 변수(i)에 0을 대입한다.
  2. while 문의 반복 유지 조건을 i < N으로 지정한다.
  3. while 문의 본문 코드 블록 안에서 필요에 따라 i의 값을 활용한다.
  4. while 문의 본문 코드 블록 안에서 i의 값을 1 증가시킨다.

컬렉션 순회하기

반복은 컬렉션을 순회하는 데도 사용된다. 순회란 컬렉션을 순서대로 돌며 내용을 조회하는 것이다. 다음은 무지개 색을 표현한 리스트의 전체 내용을 화면에 출력하는 프로그램이다. 파이참에서 while_2.py 파일을 새로 만들고, 다음 코드를 입력해로 실행해 보아라.

코드 6-21 무지개 색 리스트의 내용을 순회하며 출력 (while_2.py)

rainbow = ['Red', 'Orange', 'Yellow', 'Green', 'Blue', 'Indigo', 'Violet']
index = 0                    # ❶ 몇 번째 요소를 읽을 차례인지 기억하는 변수

while index < len(rainbow):  # ❷ index 변수가 리스트의 길이보다 작은 동안 반복
    print(rainbow[index])    # ❸ rainbow 리스트의 index 번째 요소를 화면에 출력
    index += 1               # ❹ 다음 요소를 가리키도록 index 값을 1 증가

실행 결과:

Red
Orange
Yellow
Green
Blue
Indigo
Violet

코드 6-21은 앞에서 배운 패턴과 유사하다. 하나씩 따져보자.

  • ❶에서 컬렉션의 몇 번째 요소를 읽어야 하는지 기억하는 변수 index를 정의했다. 처음에 0을 대입했으므로 컬렉션의 첫 번째 요소를 가리킨다.
  • 반복 유지 조건은 index가 컬렉션의 범위를 벗어나지 않은 동안이다. 이를 나타내기 위해 ❷에서 ‘index가 컬렉션의 길이(len(rainbow))보다 작은 동안’으로 조건을 설정했다.
  • while 문의 본문 중 ❸에서 indexrainbow[index]]와 같이 컬렉션의 index번째 요소를 가리키는 데 할용된다. 그리고 ❹에서 index의 크기가 1씩 증가한다. 따라서 반복이 1회 진행될 때마다 컬렉션의 다음 요소를 읽을 수 있다.

이와 같이 다음 번에 읽을 위치를 갱신하며 컬렉션을 순회하는 반복 패턴은 컬렉션과 함께 자주 사용된다. 이 패턴을 매번 코드로 작성하는 것은 귀찮다. 잠시 후에 컬렉션 순회에 특화된 반복 기능을 알아 볼 것이다.

흐름이 예정되지 않은 반복

수를 차례대로 세거나 컬렉션을 순서대로 읽는 것은 반복 흐름이 일정하게 정해져 있다. 하지만 반복 작업이 어떤 순서로 몇 번이나 일어날지 미리 정할 수 없는 경우도 있다. 다음 프로그램에서 while 문의 본문이 몇 번 반복 실행될지 예상해 보고, 프로그램을 작성해 실행해보자.

코드 6-22 ‘그만’을 입력할 때까지 반복하기 (while_3.py)

text = "아무 메시지나 입력하세요. 그만하려면 '그만'을 입력하세요."
while text != '그만':
    print('컴퓨터: ' + text)
    text = input()

실행 결과:

컴퓨터: 아무 메시지나 입력하세요. 그만하려면 '그만'을 입력하세요.
안녕?
컴퓨터: 안녕?
따라하지마
컴퓨터: 따라하지마
그만

코드 6-22는 사용자가 입력한 텍스트가 ‘그만’이 아닌 동안(즉, 사용자가 ‘그만’을 입력할 때까지) 사용자에게 메시지를 입력받고 화면에 출력하는 것을 반복한다. while 문은 어떤 ‘횟수’만큼이 아니라 ‘조건이 유지되는 동안’ 코드를 반복한다. 그러므로 예정되지 않은 반복을 나타내기에도 적합하다. 다음과 같이 다양한 조건을 지정할 수 있다.

  • 사용자가 엔터 키를 누를 때까지
  • 다음 공휴일 자정까지
  • 읽을 파일 내용이 남아있는 동안
  • 서버에서 응답이 올 때까지
  • 보름달이 뜰 때까지
  • 열차가 부산에 도착하기 전까지
  • 영원히

무한 반복

while 문의 조건을 잘못 지정하면 무한 반복이 발생할 수 있어 주의해야 한다. 그런데 프로그래머가 의도적으로 무한 반복을 발생시키는 경우도 있다. 무한 반복을 일으키는 방법에는 여러 가지가 있지만, while 문의 조건으로 True를 지정하는 방법이 가장 좋다. True 절대적인 참을 의미하므로 코드를 무한히 반복하겠다는 의도가 분명히 드러난다.

코드 6-23 명시적인 무한 반복 (while_4.py`)

while True:
    print('이 메시지는 무한히 반복 출력됩니다.')

실행 결과:

이 메시지는 무한히 반복 출력됩니다.
이 메시지는 무한히 반복 출력됩니다.
... (무한 반복)

무한 반복이 활용되는 곳은 많다. 몇 가지만 예를 들어 보자.

  • 사용자와 계속 상호작용하는 프로그램
  • 웹 문서를 지속적으로 탐색하며 정보를 수집하는 크롤링 프로그램
  • 음악을 무한 반복 재생하는 프로그램
  • 컴퓨터가 켜진 동안 내내 시스템을 관리하는 운영 체제

그런데 이런 프로그램들도 언젠가는 무한 반복을 중지해야 할 때가 있을 것이다. 사용자가 프로그램 종료 버튼을 눌렀거나, 더이상 탐색할 문서가 없을 수도 있다. 언젠가는 이런 예외 상황이 발생할 것이고 그 때는 반복을 중지해야 한다. 반복을 임의로 중지하는 방법은 6.2.5에서 설명한다.

요점 정리

  • while 문의 조건으로 True를 지정하여 무한 반복을 지시할 수 있다.

while 문을 사용해야 할 때

while 문을 이용하면 모든 반복 상황을 프로그래밍할 수 있다. 흐름이 예정되지 않은 반복이나 무한 반복을 나타낼 때 특히 유용하다. 하지만 작업을 순차적으로 처리하거나 컬렉션을 순회할 때는 for 문을 사용하는 것이 더 편리하다.

6.2.4 for 문: 컬렉션 순회하기

for 문은 while 문과 마찬가지로 코드를 반복 실행하는 명령이다. while 문이 여러 목적에 활용할 수 있는 범용적인 반복 기능이라면, for 문은 순차적 처리와 컬렉션 순회에 특화된 반복 기능이다. for 문을 이용하면 반복 횟수를 관리하는 데 신경을 쓰지 않고 간단히 컬렉션을 순회할 수 있다.

for 문을 작성하는 양식을 살펴보자.

for 변수 in 컬렉션:   # ❶ 첫 행
    본문              # ❷ 컬렉션의 각 항목마다 반복 실행할 코드 블록

for 문도 def 문, if 문, while 문과 같이 첫 행과 본문 행으로 구성된다. for 문의 첫 행에는 in 예약어가 있다. in 예약어의 왼쪽에는 컬렉션의 요소를 대입할 변수를, 오른쪽에는 순회하려는 컬렉션을 지정한다. 다음은 while 문으로 작성한 무지개색 순회 프로그램(코드 6-21)을 for 문을 사용하도록 수정한 것이다. 따라 작성해 실행해보자.

코드 6-24 무지개 색 리스트의 내용을 순회하며 출력 (for_1.py)

rainbow = ['Red', 'Orange', 'Yellow', 'Green', 'Blue', 'Indigo', 'Violet']

for color in rainbow:  # ❶
    print(color)       # ❷

for 문은 지정된 컬렉션의 길이만큼 본문의 코드를 반복 실행한다. ❶에서 순회할 컬렉션으로 rainbow를 지정했는데, 이 리스트의 길이가 7이므로 본문(❷)은 7번 실행된다. ❶에서 in 예약어 왼쪽에 정의한 color 변수에는 각 반복 주기마다 rainbow 리스트의 요소가 하나씩 순서대로('Red', 'Orange', …) 대입된다. 이 변수는 ❷와 같이 for 문의 본문에서 사용할 수 있다.

코드 6-24의 실행 결과는 코드 6-21과 동일하다. 이처럼 컬렉션을 순회할 때 while 문 대신 for 문을 사용하면 반복 횟수를 직접 관리하지 않아도 되고, 코드를 더 간결하게 작성할 수 있다.

한 가지 예를 더 들어보자. 다음은 시퀀스에 들어 있는 모든 수의 합계를 계산하는 함수(sum() 함수를 흉내낸 것)를 for 문을 이용해 정의한 것이다.

코드 6-25 시퀀스의 모든 수의 합을 계산하는 함수 (my_sum.py)

def my_sum(numbers):
    """numbers 의 모든 요소의 합을 반환한다."""
    total = 0  # 합계
    for n in numbers:
        total += n
    return total

print(my_sum([1, 2, 3, 4, 5]))

요점 정리

  • 컬렉션을 순회하며 컬렉션의 각 요소를 읽고 사용할 수 있다.
  • for 문을 이용하면 컬렉션을 간편하게 순회할 수 있다.

for 문과 레인지

5.2절에서 배운 레인지는 for 문과 함께 활용하기에 좋다. 다음은 for 문을 이용해 1부터 10까지의 모든 짝수의 합을 계산하는 프로그램이다. 이 프로그램을 살펴보며 레인지가 왜 필요한지 생각해 보자.

코드 6-26 1부터 10까지의 모든 짝수의 합 (for_2.py)

total = 0  # 합계

for n in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
    if n % 2 == 0:  # n 이 짝수인 경우,
        total += n  # total에 n을 더함

print(total)

실행 결과:

30

이 프로그램은 1 부터 10까지의 자연수를 담은 리스트를 순회하며 수가 짝수인 경우에만 total 변수에 더한다. 여기까지 학습한 여러분이라면 충분히 이해할 수 있을 것이다. 이 프로그램은 훌륭하게 잘 동작한다. 그러면 더하려는 수의 범위를 한 번 바꿔 보자. for 문에 지정한 리스트만 변경하면 될 것이다. for 문에 지정할 수의 범위는 ‘1부터 1천만까지의 모든 자연수’로 하자. 이 수를 나타내는 리스트는 다음과 같이 작성할 수 있다.

코드 6-27 1부터 1천만까지의 모든 자연수의 리스트

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ..., 10000000]

리스트를 직접 입력해보면 이 방법에 문제가 있다는 걸 알 것이다. 1부터 1천만까지의 리스트를 코드로 작성하기가 너무 힘들다. 그러므로 레인지를 활용하여 range(1, 10000001)와 같이 간단히 수열을 나타내자.

코드 6-28 1부터 1천만까지의 모든 짝수의 합 (for_3.py)

total = 0                     # 합계

for n in range(1, 10000001):  # 1부터 1천만까지의 레인지를 순회
    if n % 2 == 0:            # n 이 짝수인 경우,
        total += n            # total에 n을 더함

print(total)

한편, 레인지를 생성하는 range() 함수에서 세 번째 매개변수로 수열의 간격을 지정할 수 있다. 이를 이용해 ‘1부터 1천만까지의 모든 짝수’의 레인지를 바로 표현하는 것도 가능하다.

코드 6-29 1부터 1천만까지의 모든 짝수의 합 (for_4.py)

total = 0  # 합계

for n in range(2, 10000001, 2):  # 2부터 1천만까지 2씩 증가하는 레인지를 순회
    total += n                   # n이 짝수인지 검사하지 않고 total에 더해도 된다

print(total)

위 코드에서는 range() 함수가 짝수의 수열을 생성하므로, 각 요소가 짝수인지 검사하는 if 문이 없어도 된다. 이처럼 등차수열을 순회할 때 for 문과 레인지를 함께 사용하면 편리하다.

요점 정리

  • for 문과 레인지를 이용해 등차수열을 순회할 수 있다.

코드를 N회 반복 실행하기

for 문을 반드시 컬렉션 순회에만 사용해야 하는 것은 아니다. 단순히 본문의 코드를 N번 반복 실행하고 싶을 때, for 문과 레인지의 조합을 활용할 수 있다.

코드 6-30 화면에 ‘안녕?’을 N번 출력하기 (for_5.py)

print('몇 번 반복하시겠습니까?')
n = int(input())    # 반복할 횟수

for _ in range(n):  # 코드를 n번 반복 실행
    print('안녕')

실행 결과:

몇 번 반복하시겠습니까?
3
안녕
안녕
안녕

코드 6-30은 사용자가 원하는 횟수만큼 for 문의 본문을 실행한다. 이 for 문에서는 range()의 크기(본문을 몇 번 반복할지)만이 의미가 있다. 컬렉션의 각 요소가 무엇인지는 의미가 없기 때문에 요소를 대입받을 변수의 이름을 밑줄 기호 하나(_)로 지정했다. 이 이름은 사용하지 않는 무의미한 변수임을 나타낸다.

요점 정리

  • for 문과 레인지를 이용해 코드를 N회 반복 실행할 수 있다.

for 문을 사용해야 할 때

for 문은 컬렉션을 순서대로 순회할 때 편리하게 사용할 수 있다. for 문으로 할 수 있는 일은 while 문으로도 할 수 있지만 반복 과정을 제어하는 코드를 함께 작성해야 하여 불편하다.

6.2.5 continue 문과 break 문

3장에서 return 문을 배웠다. return 문을 사용하면 함수를 실행 도중에 중지시킬 수 있다. 이와 유사하게, while 문과 for 문의 실행을 도중에 중지시키는 기능이 있다. continue 문과 break 문이 그것이다. 두 명령은 for 문과 while 문 둘 다에서 똑같이 사용할 수 있다.

continue 문: 이번 주기의 실행을 중지

continue 문은 반복 도중에 ‘한 주기의 실행’을 중지하고 다음 주기로 넘어도록 하는 명령이다. continue 문을 사용하려면 for 문 또는 while 문의 본문 안에서 continue를 입력하면 된다. 다음은 for 문에서 continue 문을 사용한 예다.

코드 6-31 continue 문

for i in range(4):
    print('현재 반복 주기:', i)      # ❶
    continue                         # 현재 반복 주기를 중지하고 다음 주기로 넘어간다
    print('다음 반복 주기:', i + 1)  # ❷

실행 결과:

현재 반복 주기: 0
현재 반복 주기: 1
현재 반복 주기: 2
현재 반복 주기: 3

실행 결과에서 보듯, ❶은 실행되지만 continue 문 이후의 ❷는 실행되지 않는다.

break 문: 반복 전체를 중지

break 문은 반복의 한 주기만이 아니라 ‘반복 전체’를 중지시킨다. 사용법은 continue 문과 동일하다. 다음은 for 문에서 break 문을 사용한 예다.

코드 6-32 break 문

for i in range(4):
    print('현재 반복 주기:', i)      # ❶
    break                            # 반복 전체를 중지한다
    print('다음 반복 주기:', i + 1)  # ❷

실행 결과:

현재 반복 주기: 0

실행 결과에서 보듯, break 명령이 실행되면 반복 전체가 중지된다.

continue 문과 break 문의 활용

기본적인 반복 조건은 while 문과 for 문의 헤더에도 나타낼 수 있다. 하지만 반복 흐름을 본문의 실행 ‘도중에’ 변경해야 할 때는 continue 문과 break 문이 필요하다. 다음 코드는 사용자로부터 입력받은 수를 계속 누적하여 합계를 출력하는 프로그램이다. 이 프로그램에서 break 문과 continue 문이 어떻게 사용되었는지 살펴보자.

코드 6-33 continue 문과 break 문의 활용

total = 0

while True:                                   # ❶ 본문 코드를 무한 반복한다
    print('더할 수를 입력하세요: ', end='')
    user_input = input()
    
    if user_input == '그만':                  # ❷ '그만'이 입력되면 반복을 종료한다
        break
    
    if not user_input.isnumeric():            # ❸ 입력이 수가 아니면 다음 주기로 넘어간다
        print('잘못된 입력입니다.')
        continue
    
    total += int(user_input)
    print('합계:', total)

print('프로그램을 종료합니다.')

실행 결과:

더할 수를 입력하세요: 500
합계: 500
더할 수를 입력하세요: 2000
합계: 2500
더할 수를 입력하세요: 안녕
잘못된 입력입니다.
더할 수를 입력하세요: 10000
합계: 12500
더할 수를 입력하세요: 그만
프로그램을 종료합니다.

이 프로그램의 while 문은 기본 반복 조건과 본문 중간에서 반복 흐름을 제어해야 하는 예외상황 두 가지를 처리하고 있다.

  • 기본 반복 조건: 사용자가 수를 몇 번이나 입력할지 모르므로, ❶에서 반복 조건을 True로 하여 무한히 반복하도록 했다.
  • 예외상황 1: ❷에서 사용자가 ‘그만’을 입력한 경우. break 문으로 반복을 중지한다. break 문 다음 행의 코드는 실행되지 않으며, 반복 자체도 종료된다. 무한 반복은 스스로를 멈추지 못하므로 break 문과 함께 사용되는 경우가 많다.
  • 예외상황 2: 사용자가 입력한 텍스트가 수가 아닌 경우. 이 경우에는 덧셈을 할 수 없으므로 수를 더하는 명령을 실행해서는 안 된다. ❸에서 이런 경우를 확인하여 ‘잘못된 입력입니다’를 출력하고 continue 문으로 다음 주기로 넘어간다. continue 문 아래의 수를 더하는 코드는 실행되지 않으며, 다시 사용자로부터 수를 입력받는 코드가 반복 실행된다.

요점 정리

  • continue 문으로 반복의 한 주기를 중지하고 다음 주기로 넘어갈 수 있다.
  • break 문으로 반복 전체를 중지할 수 있다.

6.2.6 while 문과 for 문의 else 절

if 문에서 배운 else 절을 while 문과 for 문에서도 사용할 수 있다. if 문에서와 어떻게 다른지 살펴보자.

while 문에서의 else 절

while 문의 else 절은 if 문과 마찬가지로 조건이 거짓일 때 실행할 코드를 포함한다. else 절을 포함한 while 문의 양식은 다음과 같다.

while(조건):
    본문 1     # 조건이 참인 동안 반복 실행할 코드 블록
else:
    본문 2     # 조건이 거짓일 때 실행할 코드 블록

다음은 while 문에 else 절을 포함한 예다.

코드 6-34 while … else … 문의 사용예

i = 0
while(i < 3):
    print(i, '번째 실행')
    i += 1
else:
    print('반복 완료')

실행 결과:

0 번째 실행
1 번째 실행
2 번째 실행
반복 완료

if 문에서는 조건이 참인지 거짓인지에 따라 else 절의 본문이 실행될 수도 그렇지 않을 수도 있다. 그런데 while 문은 조건이 거짓이 될 때 반복이 끝나므로, 반복이 끝날 때 항상 else 절의 본문이 실행될 것이라고 생각할 수 있다. 정상적으로 반복이 끝난 경우에는 그렇다. 하지만 break 문을 통해 반복이 종료된 경우에는 ‘조건이 거짓으로 평가’된 것이 아니므로 else 절의 본문이 실행되지 않는다.

코드 6-35 else 절이 실행되지 않는 경우

i = 0
while(i < 100):
    print(i, '번째 실행')
    i += 1
    if (i > 2):
        print('반복 중지')
        break
else:
    print('반복 완료')

실행 결과:

0 번째 실행
1 번째 실행
2 번째 실행
반복 중지

for 문에서의 else 절

for 문의 else 절은 전체 반복 과정이 정상적으로 종료된 직후에 본문의 코드를 실행한다. break 문으로 반복이 중지된 경우는 정상적인 종료가 아니므로 else 문의 본문이 실행되지 않는다. else 절을 포함한 양식은 다음과 같다.

for 변수 in 컬렉션:
    본문 1            # 컬렉션의 각 항목마다 반복 실행할 코드 블록
else:
    본문 2            # 반복이 정상 종료된 직후 실행할 코드 블록

다음은 for 문에 else 절을 포함한 예다.

코드 6-36 for … else … 문의 사용예

for i in range(3):
    print(i, '번째 실행')
else:
    print('반복 완료')

실행 결과:

0 번째 실행
1 번째 실행
2 번째 실행
반복 완료

반복에서 else 절의 활용

단순히 반복이 끝난 후에 코드를 실행해야 한다면 else 절을 사용할 필요 없이 그저 while 문과 for 문의 다음 행에 그 코드를 입력하면 된다. else 절의 가치는 반복이 정상적으로 종료되었는지 아니면 임의로 중지되었는지를 구분하는 데 있다. 다음은 이를 활용해 수 리스트에서 첫 번째 짝수를 찾아내는 프로그램이다.

코드 6-37 첫 짝수 찾기

def 첫_짝수_찾기(numbers):
    """numbers에서 첫 번째 짝수를 찾아 화면에 출력한다."""
    for n in numbers:
        if n % 2 == 0:
            print(n, '이 첫 짝수입니다.')
            break;
    else:
        print('짝수가 없습니다.')

첫_짝수_찾기([1, 3, 5, 33, 47, 55])
첫_짝수_찾기([7, 5, 6, 72, 19, 81])

실행 결과:

짝수가 없습니다.
6 이 첫 짝수입니다.

위 코드의 첫_짝수_찾기() 함수는 짝수가 중간에 발견되었을 때는 반복을 중지하며 발견된 짝수를 알려주고, 반복이 다 끝날 때까지(정상 종료시까지) 짝수를 찾지 못했을 때는 짝수가 없다고 알려준다. else 절을 활용하지 않았다면 별도의 변수를 사용해 짝수를 발견했는지 아닌지 기억해야 했을 것이다.

요점 정리

  • while 문에서 else 절의 본문은 반복이 정상적으로 종료되었을 때 실행된다.
  • for 문에서 else 절의 본문은 순회가 정상적으로 종료되었을 때 실행된다.
  • 반복 도중 break 문이 실행되면 else 절의 본문이 실행되지 않는다.

6.2.7 반복 중첩하기

코드 블록은 또다른 코드 블록을 포함할 수 있다. 그동안 def 문 안에서 if 문과 for 문을 사용해 보기도 했고, if 문 안에서 if 문을 정의한 표현도 보았다. 코드 블록의 중첩은 필요한만큼 여러 번 할 수 있다. 한 단계마다 들여쓰기를 네 번씩 해야 한다는 점, 같은 단계의 코드 블록은 같은 수준만큼 들여써야 한다는 점만 주의하면 된다. for 문과 while 문의 본문도 코드 블록이므로 반복을 서로 중첩하는 것도 가능하다. 반복을 중첩하면 표를 그리거나 2차원, 3차원, … n차원의 컬렉션을 순회하는 등의 작업을 나타낼 수 있다.

곱셈표 출력하기

다음은 for 문 두 개를 중첩하여 곰셈표를 출력하는 프로그램이다. 파이참에서 for_in_for1.py 파일을 만들고 다음 코드를 입력해 실행해 보자.

코드 6-38 for 문 중첩하기 (for_in_for1.py)

for i in range(2, 10):          # 바깥쪽 for 문: 2에서 9까지 순회
    for j in range(1, 10):      # 안쪽 for 문:   1에서 9까지 순회
        print(i * j, end='  ')  # i * j 출력
    print()                     # 줄바꿈

실행 결과:

2  4  6  8  10  12  14  16  18  
3  6  9  12  15  18  21  24  27  
4  8  12  16  20  24  28  32  36  
5  10  15  20  25  30  35  40  45  
6  12  18  24  30  36  42  48  54  
7  14  21  28  35  42  49  56  63  
8  16  24  32  40  48  56  64  72  
9  18  27  36  45  54  63  72  81  

코드 6-38이 실행되는 과정을 한 번 생각해보자.

  1. 바깥쪽의 for 문은 range(2, 10)을 순회하므로 본문의 코드는 8회 실행된다.
  2. 안쪽의 for 문은 바깥 쪽의 본문이 한 번 실행될 때마다 range(1, 10)을 순회한다. 바깥에서 8번, 안에서 9번 반복되므로 print(i * j, end=' ')은 총 8 * 9 = 72회 실행된다.
  3. 화면에 출력할 수는 i * j로 계산했는데, 이는 바깥쪽 for 문의 변수 i와 안쪽 for 문의 변수 j를 함께 사용한 것이다. i에 2가 대입된 동안, j에는 1, 2, 3, 4, …가 차례로 대입되므로, 화면에는 2, 4, 6, 8, … 이 차례대로 출력된다.
  4. 안쪽 for 문을 실행한 후에는 print() 명령으로 줄바꿈을 하도록 했다. 이 명령도 바깥쪽 for 문의 일부분이므로(들여쓰기로 구별할 수 있다) 총 8회 실행된다.

중첩 반복 표현은 중첩된 컬렉션을 순회할 때도 많이 사용된다. 복잡한 컬렉션을 순회하는 방법은 7장에서 좀 더 알아보기로 하자.

요점 정리

  • 반복 코드 속에 반복 코드를 작성하여 중첩할 수 있다.

연습문제

연습문제 6-6 5의 배수의 합계 (while 문을 사용하여)

1백 이상, 1만 미만인 자연수 가운데 5의 배수를 모두 합하면 얼마인지 while 문을 사용해 계산해 보아라.

  • 힌트: 초기값이 1백이고 각 반복 주기마다 5씩 증가하는 변수를 사용해 보자.

연습문제 6-7 5의 배수의 합계 (for 문을 사용하여)

연습문제 6-6의 문제를 for 문과 레인지를 사용해 계산해 보아라.

연습문제 6-8 가장 큰 수 계산

리스트 하나를 매개변수로 전달받아, 리스트에서 가장 큰 요소를 반환하는 함수를 정의해 보아라. 단, max() 함수를 사용해서는 안 된다.

힌트: 가장 큰 수를 기억하기 위해 변수를 사용하자.

연습문제 6-9 소수 검사

약수가 1과 자기 자신 뿐인 자연수를 소수(prime number)라고 한다. 어떤 수를 입력받아 그 수가 소수인지 검사하여 True 또는 False를 반환하는 함수 is_prime()을 정의하라. 그 후, 정의한 함수를 이용해 1 이상 100 미만의 모든 소수의 합을 계산하라.

힌트: A를 B로 나눈 나머지가 존재한다면 B는 A의 약수가 아니다.