Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

8 while 반복문

Updated: 10 mrt 2026

while 반복문은 특정 조건이 만족되는 동안 동일한 명령문을 반복 실행한다. 형식은 다음과 같다.

while 논리식:
    명령문

while 논리식이 쓰여진 행의 끝에 콜론 : 이 사용되고 그 아래에 있는 명령문은 들여쓰기 되었음에 주의한다. 논리식True로 유지되는 동안 들여쓰기된 명령문이 반복된다.

8.1기본 활용법

for 반복문은 리스트 또는 range() 함수처럼 일정 구간에서 규칙성 있게 변하는 값들을 대상으로 동일한 명령문을 반복 수행할 때 사용한다. 반면에 while 반복문은 일정 구간이나 규칙이 없어도 특정 조건이 만족되는 동안 계속해서 동일한 명령문을 반복 실행하고자 할 때 사용한다.

아래 “수 알아맞히기 게임” 코드는 1부터 100 사이의 정수 하나를 입력하면 입력한 값을 secret 변수에 할당된 17과 비교해서 경우에 따라 적절한 문장을 출력한다. 예를 들어 33을 입력하면 '너무 커요!'를 출력한다.

print("수 알아맞히기 게임에 환영합니다.")

secret = 17
guess = int(input("1부터 100 사이의 정수 하나를 입력하세요: "))

if guess == secret:
    print("맞았습니다!")
elif guess > secret:
    print("너무 커요!")
else:
    print("너무 작아요!")

print("게임 종료!")
수 알아맞히기 게임에 환영합니다.
1부터 100 사이의 정수 하나를 입력하세요: 33
너무 커요!
게임 종료!

그런데 위 코드는 입력한 답이 맞든 틀리든 바로 종료한다. 따라서 정답을 입력할 때가지 반복해서 사용자로부터 입력을 받도록 하고자 한다. 그런데 입력을 몇 번 받으면 답을 맞힐 것인지 미리 알 수 없다. 이런 경우에 while 반복문을 사용한다.

아래 코드는 입력값이 17을 맞히지 못하면 계속해서 입력을 받도록 한다. 또한 게임 참여자가 입력한 값 guesssecret와 다르면 큰지 또는 작은지 여부를 알려주면서 게임 참여자가 예측 범위를 줄여 나갈 수 있도록 도와준다. while guess != secret이 실행되기 전에 guess = -1로 변수 할당문을 선언하는 이유는 while 반복문이 최소 한 번은 실행되도록 하기 위함이다.

첫 입력값을 50으로 한 다음에 secret 보다 큰지 작은지 여부에 따라 적절한 값을 입력하면 언젠가는 답을 맞추게 된다.

print("수 알아맞히기 게임에 환영합니다.")

secret = 17
guess = -1   # 이어지는 while 반복문이 최소 한 번은 실행되도록 함

while guess != secret:
    guess = int(input("1부터 100 사이의 정수 하나를 입력하세요: "))
    if guess == secret:
        print("맞았습니다!")
    elif guess > secret:
        print("너무 커요!")
    else:
        print("너무 작아요!")

print("게임 종료!")
수 알아맞히기 게임에 환영합니다.
1부터 100 사이의 정수 하나를 입력하세요: 50
너무 커요!
1부터 100 사이의 정수 하나를 입력하세요: 25
너무 커요!
1부터 100 사이의 정수 하나를 입력하세요: 12
너무 작아요!
1부터 100 사이의 정수 하나를 입력하세요: 18
너무 커요!
1부터 100 사이의 정수 하나를 입력하세요: 15
너무 작아요!
1부터 100 사이의 정수 하나를 입력하세요: 16
너무 작아요!
1부터 100 사이의 정수 하나를 입력하세요: 17
맞았습니다!
게임 종료!

8.2리스트와 while 반복문

아래 코드는 1부터 5까지의 정수를 더하는 코드를 for 반복문으로 구현한다.

one2five = [1, 2, 3, 4, 5]

sum_list = 0
for item in one2five:
    sum_list += item 

print("1부터 5까지 정수들의 합:", sum_list)
1부터 5까지 정수들의 합: 15

동일한 기능의 코드를 while 반복문으로 구현할 수 있다. 그런데 리스트를 대상으로 while 반복문을 실행하려면 리스트의 길이, 즉 리스트에 포함된 항목들의 개수와 인덱싱을 활용한다. 이유는 for 반복문과는 달리 while 반복문은 리스트의 항목을 직접 가리키는 기능을 제공하지 않기 때문이다.

아래 코드는 1부터 5까지의 정수를 더하는 코드를 while 반복문으로 구현한다.

  • len() 함수가 리스트에 포함된 항목들의 개수를 반환한다.

  • 인덱스를 가리키는 변수 i의 값을 반복문이 한 번 실행될 때마다 인위적으로 1씩 키워주는 업데이트를 실행한다.

  • i가 리스트의 길이보다 같아질 때까지 항목을 누적해서 더하는 과정을 반복한다.

one2five = [1, 2, 3, 4, 5]

sum_list = 0
i = 0
while i < len(one2five):
    item = one2five[i]
    sum_list += item 
    i += 1           

print("1부터 5까지 정수들의 합:", sum_list)
1부터 5까지 정수들의 합: 15

코드에 포함된 아래 while 반복분이 실행될 때 i 변수는 먼저 0을 가리키기에 item 변수는 0번째 인덱스의 값인 1을 가리킨다.

while i < len(one2five):
    item = one2five[i]
    sum_list += item 
    i += 1           

따라서 sum_list가 0이 아닌 1을 가리키게 된다. 이후 i가 1로 바뀌고 다시 반복문의 본문의 처음으로 돌아간다. 이때 item은 1번 인덱스 항목인 2를 가리키고 반복문의 본문을 다시 실행한다.

이 과정을 i가 4를 가키릴 때까지 반복하면 sum_listone2five 리스트의 0번 인덱스의 항목부터 마지막 항목까지 더한 값을 가리키게 되고 i가 5, 즉 one2five의 길이와 같아지게 되어 while 반복문의 실행을 종료하고 다음 명령문으로 넘어간다.

Python Tutor 활용 while 반복문 설명

아래 그림은 위 코드의 while 반복문이 실행되어 item 변수가 선언된 순간에 sum_listi는 아직 초기화 상태이고 item은 0번 인덱스 항목인 1을 가리키고 있음을 보여준다.

<그림 출처: Python Tutor>

반면에 아래 그림은 while 반복문이 세 번째로 실행되어 i는 2, item은 3을 가리키지만 sum_list는 아직 업데이트 이전 상태를 보여준다.

<그림 출처: Python Tutor>

while 반복문이 계속 실행되어 i가 5가 되면 논리식 i < len(one2five)가 거짓이 되고 반복문을 더 이상 실행하지 않는다. sum_list는 모든 항목이 더해진 상태인 15를 가리킨다.

<그림 출처: Python Tutor>

8.3continue와 break

for반복문 뿐만 아니라 while 반복문의 실행 도중에도 continue 명령문과 break 명령문이 실행되면 특정 경우를 건너뛰도록 하거나 while 반복문의 실행을 중간에 중단된다.

continue 명령문

continue 명령문이 반복문 실행 도중에 실행되면 반복문의 실행을 중지하고 다시 반복문의 처음으로 돌아간다.

  • for 반복문: 현재 처리중인 경우를 바로 건너 뛰고 다음 경우로 넘어감.

  • while 반복문: while 반복문의 처음으로 바로 돌아감.

아래 프로그램을 실행하면 1부터 9까지의 정수를 대상으로 차례대로 3의 배수 여부를 판단한다.

num이 차례대로 1, 2, 3, ... 등을 할당받을 때마다 3의 배수 여부를 판단한다.

  • num에 할당된 값이 3의 배수인 경우: 3의 배수임을 확인하는 문자열 출력

  • num에 할당된 값이 3의 배수가 아닌 경우: continue 명령문이 실행되어 바로 아랫줄의 print() 명령문을 실행하지 않고 반복문의 다음 경우로 이동함. 즉, num이 다음 항목을 가리키도록 함.

결국 num이 1부터 시작해서 차례대로 값을 할당받으면 1, 2, 4, 5, 7, 8의 경우는 continue 명령문에 의해 무시되는 효과가 발생한다.

for num in range(1, 10):
    if num % 3 == 0:
        print(num, "은(는) 3의 배수!")
    else:
        continue

print("1과 10 사이에서 3의 배수를 확인했음!")
3 은(는) 3의 배수!
6 은(는) 3의 배수!
9 은(는) 3의 배수!
1과 10 사이에서 3의 배수를 확인했음!

아래 코드는 위 코드와 동일하게 작동한다. 대신 while 반복문을 사용한다.

num = 1
while num < 10:
    if num % 3 == 0:
        print(num, "은(는) 3의 배수!")
        num += 1
    else:
        num += 1
        continue
        
print("1과 10 사이에서 3의 배수를 확인했음!")
3 은(는) 3의 배수!
6 은(는) 3의 배수!
9 은(는) 3의 배수!
1과 10 사이에서 3의 배수를 확인했음!

num을 1로 초기화 하고 num += 1 명령문을 while 반복문이 한 번 실행될 때 마다 실행되도록 함에 주의한다. 그렇지 않으면 num이 가리키는 값이 업데이트되지 않아 무한 반복에 빠질 수 있다. 특히 num이 3의 배수가 아닌 값을 가리킬 때 continue가 실행되기 전에 num을 업데이트 해야 한다.

예를 들어 아래 코드를 실행하면 반복문의 실행이 멈추지 않는다.

num = 0
while num < 10:
    if num % 3 == 0:
        print(num, "은(는) 3의 배수!")
    else:
        continue

    num += 1

print("1과 10 사이에서 3의 배수를 확인했음!")

break 명령문

break 명령문은 for 또는 while 반복문의 실행을 중지시킨다. 예를 들어, 아래 프로그램을 실행하면 1부터 9까지의 정수를 대상으로 차례대로 3의 배수 여부를 판단한다. num 변수에 차례대로 1, 2, 3, ... 를 할당할 때마다 3의 배수 여부를 판단한다.

  • 3의 배수가 아닐 때: num이 가리키는 값이 3의 배수가 아님을 출력함.

  • 3의 배수인 경우: 3의 배수를 찾았다고 알린 후 바로 break 명령문이 실행되어 반복문이 종료됨. 즉, "3의 배수 찾았음"을 출력하는 바로 다음 줄에 위치한 print() 함수의 호출은 실행되지 않음.

즉, num 변수가 1 또는 2를 가리킬 때는 3의 배수가 아님을 알리고 3을 가리킬 때는 3의 배수임을 알리고 바로 for 반복문의 실행을 종료시킨다. 원래는 num 변수가 4, 5, ... 등을 가리키는 경우도 반복해야 하지만 더이상 그러지 않는다.

이후 마지막 줄의 print() 함수 호출은 실행되어 프로그램의 종료를 알린다. break는 자신을 포함한 반복문의 실행을 멈추게 하지만 전체 프로그램은 차례대로 끝까지 실행된다.

for num in range(1, 10):
    if num % 3 != 0:
        print(num, "은(는) 3의 배수 아님!")
    else:
        print(num, "은(는) 3의 배수!")
        break
        
print("프로그램 종료!")
1 은(는) 3의 배수 아님!
2 은(는) 3의 배수 아님!
3 은(는) 3의 배수!
프로그램 종료!

아래 코드는 위 프로그램을 while 반복문으로 구현하였으며 실행되는 과정은 위 코드와 동일하다. 즉, num에 3이 할당되어 3의 배수를 가리키는 순간 break 명령문이 실행되어 반복문이 바로 멈추고 마지막 줄의 print() 함수가 호출된다.

num = 1

while num < 10:
    if num % 3 != 0:
        print(num, "은(는) 3의 배수 아님!")
    else:
        print(num, "은(는) 3의 배수!")
        break
        
    num += 1
        
print("프로그램 종료!")
1 은(는) 3의 배수 아님!
2 은(는) 3의 배수 아님!
3 은(는) 3의 배수!
프로그램 종료!

continue와 break 영향 범위

continuebreak 명령문은 자신을 포함한 for 또는 while 반복문의 실행에만 영항을 준다.

예를 들어 동일한 일을 하는 아래 두 코드를 실행하면 1과 2를 출력한 후에 forwhile 반복문의 실행이 멈춘다. 그리고 마지막 줄에 위치한 print("코드 실행 종료") 명령문이 실행되어 화면에 "코드 실행 종료"가 출력된다.

  • for 반복문

for num in range(1, 5):
    print(num)
    if num == 2:
        break
    
print("코드 실행 종료!")
1
2
코드 실행 종료!
  • while 반복문

num = 1

while num < 5:
    print(num)
    if num == 2:
        break
    num += 1
    
print("코드 실행 종료!")
1
2
코드 실행 종료!

반복문이 중첩된 경우에는 자신을 포함하면서 가장 가까운 반복문에만 영향을 준다. 아래 코드의 2번 줄에서 시작하는 while 반복문은 2부터 10까지의 정수를 대상으로 소수 여부에 따라 다음 일을 진행한다.

  • 변수 n이 소수가 아닐 때

    • n을 2의 곱으로 표현한 후에 is_primeFalse로 지정한 후에 break 명령문 실행되어 for 반복문 종료.

    • 이후에 n을 1 키운 다음에 while 반복문의 다음 경우로 넘어감.

  • 변수 n이 소수를 가리킬 때

    • 소수임을 출력 후 n을 1 키운 후 while 반복문의 다음 경우로 넘어감.

n = 2
while 2 <= n < 11:
    is_prime = True # 이 값이 계속 유지되면 소수임

    for x in range(2, n):
        if n % x == 0:
            is_prime = False
            print("-", n, "=", x, "*", n//x)
            break
    
    if is_prime:
        print(f"{n}은 소수")
        n += 1
        continue
        
    n += 1
2은 소수
3은 소수
- 4 = 2 * 2
5은 소수
- 6 = 2 * 3
7은 소수
- 8 = 2 * 4
- 9 = 3 * 3
- 10 = 2 * 5

8.4무한 반복과 break 명령문

아래 코드를 실행하면 사용자로부터 계속해서 값을 입력받으며 절대로 멈추지 않는다. 이유는 while True에서 사용된 True 표현식이 항상 참이기 때문이다.

while True:
    line = input('단어입력: ')
    print(line)

print('종료합니다!')

만약 위 코드를 실행했다면 파이썬 실행기를 강제로 종료시키거나 컴퓨터를 꺼야 한다. 이처럼 반복문이 끝나지 않고 계속 실행되는 현상이 무한 반복infinite loop이다.

반면에 아래 코드는 사용자로부터 '중지' 단어가 입력되는 순간 반복문을 중지한다. 그런 다음 마지막 줄의 print() 함수 호출을 실행해서 프로그램의 종료를 알린다.

while True:
    line = input('단어 입력: ')
    if line == '중지':
        break
    print('입력한 단어:', line)

print('종료합니다!')
단어 입력: 파이썬
입력한 단어: 파이썬
단어 입력: 좋아요!
입력한 단어: 좋아요!
단어 입력: 중지
종료합니다!

무한 반복은 게임 프로그래밍에서 자주 사용된다. 게임 종료 시점은 게임의 전개 과정에 따라 달라지기에 미리 알 수 없다. 따라서 게임 진행 전체를 관장하는 코드는 기본적으로 while True로 시작하는 무한 반복을 활용한다. 단, 게임이 종료되는 조건이 되면 break 명령문 등과 같이 반복문의 실행을 종료시키거나 프로그램 자체를 종료시키는 특정 명령문이 실행되도록 해야 한다.

예를 들어, 거북이 경주 게임에서 두 마리의 거북이가 목표 지점에 다다르기 위해 경주를 한다.

코드를 실행한 다음에 Enter키를 누르면 각각의 거북이가 무작위로 앞으로 전진한다. 한 마리의 거북이가 먼저 목표 지점에 다다르면 승자가 결정되고 게임이 멈추는데 그때가 언제인지는 절대로 미리 알 수 없다.

따라서 경주를 진행하는 반복문이 while True로 시작하며 한 마리의 거북이가 목표 지점에 다다르면 반복문의 실행이 멈추도록 break 명령문이 사용되었다.

참고로 아래 거북이 경주 게임 코드는 2차원 컴퓨터 그래픽스를 지원하는 turtle 모듈을 사용하며 구글 코랩에서는 실행되지 않는다. 코드 설명과 실행은 코딩 한 시간: 거북이 소개에서 확인한다.

import turtle
import random

# Tina 생성 후 출발점에 위치시키기
tina = turtle.Turtle()
tina.color("green")
tina.shape("turtle")
tina.penup()
tina.goto(-180,50)

# Tommy 생성 후 출발점에 위치시키기
tommy = turtle.Turtle()
tommy.color("blue")
tommy.shape("turtle")
tommy.penup()
tommy.goto(-180,-50)

# Tina의 목표지점에 원 그리고 출발점으로 되돌아오기
tina.goto(170,20)
tina.pendown()
tina.circle(20)
tina.penup()
tina.goto(-180,50)

# Tommy의 목표지점에 원 그리고 출발점으로 되돌아오기
tommy.goto(170,-80)
tommy.pendown()
tommy.circle(20)
tommy.penup()
tommy.goto(-180,-50)

# 게임 실행
def rolling_dice(t):
    t_turn = input("엔터키를 누르면 주사위가 던져집니다!")
    die_outcome = random.randint(1, 6)
    print("주사위 값:", die_outcome)
    print("전진 거리:", 10*die_outcome)
    t.fd(10 * die_outcome)

while True:
    rolling_dice(tina)

    if tina.pos()[0] >= 130:
        tina.write("I won!")
        print("Tina won!")
        break

    rolling_dice(tommy)

    if tommy.pos()[0] >= 130:
        tommy.write("I won!")
        print("Tommy won!")
        break

8.5예제

예제 1

다음 모양을 출력하는 코드를 작성한다. 두 개의 별 기호 사이에 공백(space)이 사용됨에 주의한다. 공백도 하나의 기호로 취급된다. 단, print() 함수와 while 반복문은 한 번씩만 활용한다.

* * * * *  
* * * *  
* * *  
* *  
*
*
* *
* * *
* * * *
* * * * *

답:

별 기호와 공백으로 구성된 문자열, 즉 "* "이 차례대로 5, 4, 3, 2, 1 번씩, 이후에 다시 1, 2, 3, 4, 5 번씩 반복된다. While 반복문: 총 10번 출력하며 처음 5번과 나중 5번이 대칭을 이룬다. num이 0부터 9까지 변할 때 '* ' 문자열이 반복되는 횟수를 stars 변수에 할당하는데 num에 할당된 값이 5일 때를 기준으로 달라진다.

num = 0
while num < 10:
    if num < 5:
        stars = 5 - num
    else:
        stars = num - 4
        
    print("* " * stars)
        
    num += 1
* * * * * 
* * * * 
* * * 
* * 
* 
* 
* * 
* * * 
* * * * 
* * * * * 

예제 2

0부터 100까지의 숫자 중에서 3 또는 7의 배수를 모두 더한 결과를 다음과 같이 출력하는 프로그램을 작성하라.

0~100의 숫자 중 3의 배수와 7의 배수들의 합: 2208

힌트: range() 함수와 for 반복문 활용

답:

0부터 100까지의 정수들의 구간은 range(0, 101)로 표현한다. 그리고 num 하나의 정수를 가리킬 때 num이 3의 배수이거나 7의 배수인지 여부는 다음 표현식이 판단한다.

num % 3 == 0 or num % 7 == 0

이를 정리하여 0부터 100까지의 정수들 중에서 3의 배수이거나 7의 배수의 합을 계산하는 코드를 다음과 같다. sum 변수는 3 또는 7의 배수만을 더한 누적합을 기억하는 장치로 이용된다.

sum = 0

for num in range(0, 101):
    if num % 3 == 0 or num % 7 == 0:
        sum += num
        
print("0~100의 숫자 중 3의 배수와 7의 배수들의 합:", sum)
0~100의 숫자 중 3의 배수와 7의 배수들의 합: 2208

예제 3

사용자로부터 3보다 큰 양의 정수 n을 입력 받으면, 1과 n을 제외한 n의 약수를 모두 출력하는 코드를 구현하라. 예를 들어 24가 입력되었을 때 다음과 같이 출력되어야 한다.

24의 약수: 2, 3, 4, 6, 8, 12, 

단, while 반복문을 이용한다.

답:

3보다 큰 양의 정수 n의 약수는 보통 1부터 n까지 확인하지만 여기서는 양 끝수는 제외한다. 따라서 while 반복문을 이용하여 2부터 시작해서 n-1까지의 정수에 대해 n의 약수인지 여부를 판단한다.

n = int(input("3보다 큰 양의 정수 입력:"))
print()

print(n, "의 약수:", sep='', end=' ')
num = 2
while num < n:
    if n % num == 0:
        print(num, end=", ")
    num += 1
3보다 큰 양의 정수 입력:24

24의 약수: 2, 3, 4, 6, 8, 12, 

예제 4

사용자로부터 2부터 9 까지의 정수 중에 하나를 입력 받아 구구단을 아래 형식으로 출력하는 코드를 while 반복문을 이용하여 작성한다. 예를 들어 3을 입력받으면 3단을 다음과 같이 출력한다.

3 * 2 = 6
3 * 3 = 9
3 * 4 = 12
3 * 5 = 15
3 * 6 = 18
3 * 7 = 21
3 * 8 = 24
3 * 9 = 27

2부터 시작해서 while 반복문의 본문이 실행될 때마다 1씩 커지는 방식으로 업데이트되는 변수 num을 활용한다. 아래 코드를 실행한 다음 3을 입력하면 3단을 출력한다.

n = int(input("2에서 9사이 정수 하나 입력: "))

num = 2
while num < 10:
    print(n, '*', num, '=', n*num)
    num += 1
2에서 9사이 정수 하나 입력: 3
3 * 2 = 6
3 * 3 = 9
3 * 4 = 12
3 * 5 = 15
3 * 6 = 18
3 * 7 = 21
3 * 8 = 24
3 * 9 = 27

5를 입력하면 5단이 출력된다.

n = int(input("2에서 9사이 정수 하나 입력: "))

num = 2
while num < 10:
    print(n, '*', num, '=', n*num)
    num += 1
2에서 9사이 정수 하나 입력: 5
5 * 2 = 10
5 * 3 = 15
5 * 4 = 20
5 * 5 = 25
5 * 6 = 30
5 * 7 = 35
5 * 8 = 40
5 * 9 = 45

예제 5

아래 코드의 실행 결과를 설명하라.

n = 2
while n < 10:
    if n % 2 == 1:
        print("-", n, "은(는) 홀수다.")
    
    n += 1
    continue

print("실행 종료!")        
- 3 은(는) 홀수다.
- 5 은(는) 홀수다.
- 7 은(는) 홀수다.
- 9 은(는) 홀수다.
실행 종료!

답:

while 반복문은 n이 2부터 10까지의 정수를 차례대로 가리키는 동안 실행된다.

  • 3번 줄에서 시작하는 if 조건문은 n이 홀수일 때 홀수임을 확인한 다음 n을 1 키운다.

  • 이후에 7번 줄에서 continue 명령문이 실행되어 while 반복문의 처음으로 돌아간다.

  • while 반복문이 종료된 후에 이어지는 명령문이 계속해서 실행되어 마지막 줄의 print("실행 종료!")에 의해 코드의 실행이 종료되었음을 확인해준다.

예제 6

아래 코드의 실행 결과를 설명하라.

i = 0
while i < 4:
    j = 0
    while j < 4:
        if i == j:
            j += 1
            break
        print([i, j])
        j += 1
    i += 1
[1, 0]
[2, 0]
[2, 1]
[3, 0]
[3, 1]
[3, 2]

답:

i가 0부터 3까지 변할 때 다음을 실행한다.

  • 각각의 i에 대해 j가 0부터 3까지 변하면서 i == j 가 참이 되는 순간까지 [i, j] 출력.

결론적으로 i > j인 경우에만 [i, j]를 출력한다.

예제 7

아래 코드의 실행 결과를 설명하라.

i = 0
while i < 4:
    j = 0
    while j < 4:
        if i == j:
            j += 1
            continue
        print([i, j])
        j += 1
    i += 1
[0, 1]
[0, 2]
[0, 3]
[1, 0]
[1, 2]
[1, 3]
[2, 0]
[2, 1]
[2, 3]
[3, 0]
[3, 1]
[3, 2]

답:

i가 0부터 3까지 변할 때 다음을 실행한다.

  • 각각의 i에 대해 i < j 가 거짓인 경우에만 리스트 [i, j] 출력.

  • 각각의 i에 대해 j가 0부터 3까지 변하면서 i == j 가 참이 되는 순간 continue 명령문이 실행됨.

결론적으로 ij가 다른 경우에만 [i, j]를 출력한다.

예제 4

(1) 아래 코드의 실행 결과를 설명하라.

def counter_func1() :
    i = 1
    while i < 100 :
        print("*" * i)
        return i
        i += 1

count = counter_func1()
print("while 반복문의 본문 반복 횟수:", count, "번")
*
while 반복문의 본문 반복 횟수: 1 번

위 코드의 실행 순서는 다음과 같다.

  • 매개변수를 사용하지 않는 counter_func1() 함수가 정의된다.

  • count = counter_func1() 변수 할당 명령문이 실행된다. 따라서 count 변수에 할당할 값을 정하기 위해 counter_func1() 함수가 인자 없이 호출된다.

  • counter_func1() 함수 호출

    • 변수 i에 1이 할당되고 while 반복문이 실행된다.

    • i < 100 이 참이기에 먼저 "*" * 1, 즉 "*"가 출력된다.

    • return i 명령문에 의해 당시 i가 가리키는 값인 1을 반환한다. 함수는 실행 도중에 return 명령문에 의해 반환값이 지정되는 순간 바로 지정된 반환값을 반환하면서 실행을 멈춘다. 따라서 변수 업데이트 명령문인 i += 1은 실행되지 않은 채 while 반복문 또한 종료된다.

  • count 변수에 할당된 값은 함수 호출 과정에서 생성된 지역 변수 i가 가리키는 값이며 이 값이 while 반복문의 반복 횟수와도 일치한다.

  • 마지막 줄의 print() 명령문이 실행되어 while 반복문의 본문이 1번만 실행되었음을 확인해준다.

(2) 아래 코드의 실행 결과를 설명하라.

def counter_func2(num) :
    i = 1
    while i < num:
        print(i)
        if i == 3 :
            return i
        print("*" * i)
        i += 1
    print("=" * i)
    return i

return_value = counter_func2(100)
print("반환값", return_value)
1
*
2
**
3
반환값 3

  • return_value 변수에 값을 할당하기 위해 먼저 counter_func2(100)를 호출한다.

  • counter_func2(100) 이 호출되면 i가 가리키는 값이 1에서 3까지 변하는 동안 while 반복문이 실행된다.

  • 이유는 반복문의 본문에 있는 if 조건문에 있는 논리식이 i가 3일 가리킬 때 참이고 그러면 return ... 명령문이 실행되어 함수의 실행이 종료되기 때문이다.

  • 따라서 i가 1일 때 정수 1과 별 하나, 2일 때 정수 2와 별 두개, 3일 때는 정수 3만 출력하고 곧바로 반환값이 3으로 지정된다.

예제 7

아래 grid2() 함수는 2x2 모양의 격자 무늬를 그린다.

pm = "+ - - "
ps = "|     "
plus_sign = "+"
pipe_sign = "|"

def print_pm2():
    pm_line = pm * 2 + plus_sign
    print(pm_line)

def print_ps2():
    ps_line = ps * 2 + pipe_sign
    print(ps_line, ps_line, sep="\n")

def grid2():
    count = 0
    while count < 2:
        print_pm2()
        print_ps2()
        count += 1

    print_pm2()
grid2()
+ - - + - - +
|     |     |
|     |     |
+ - - + - - +
|     |     |
|     |     |
+ - - + - - +

grid2() 함수를 구현하는 코드를 수정해서 아래 조건을 만족하는 grid() 함수를 정의하라. 단, 양의 정수를 인자로 받는 매개변수 n 을 사용한다.

조건:

n 은 그려지는 격자 칸의 개수를 나타낸다. 즉, grid(2)grid2() 와 동일한 2x2 모양의 격자를 그리며, grid(4) 는 아래처럼 4x4 모양의 격자를 그려야 한다.

+ - - + - - + - - + - - +
|     |     |     |     |
|     |     |     |     |
+ - - + - - + - - + - - +
|     |     |     |     |
|     |     |     |     |
+ - - + - - + - - + - - +
|     |     |     |     |
|     |     |     |     |
+ - - + - - + - - + - - +
|     |     |     |     |
|     |     |     |     |
+ - - + - - + - - + - - +

주어진 코드를 수정해서 보다 일반화된 기능을 갖는 코드를 구현하려면 먼저 기존 코드를 자세히 살펴봐야 한다.

grid2() 함수는 print_pm2() 함수와 print_ps2() 함수를 이용한다. 따라서 두 함수의 기능을 살펴 보자.

  • print_pm2() 함수 호출

print_pm2()
+ - - + - - +

즉, + - - 를 두번, 마지막에 +를 출력한다.

  • print_ps2() 함수 호출

print_ps2()
|     |     |
|     |     |

즉, | 를 두번, 마지막에 +를 출력하는 과정을 두 번 반복한다.

결국 print_pm2()print_ps2()를 연속 호출하면 아래 모양이 만들어진다.

print_pm2()
print_ps2()
+ - - + - - +
|     |     |
|     |     |

위 코드를 두 번 반복한 다음에 마지막에 다시 print_pm2() 를 호출하면 아래 모양이 완성된다.

count = 0
while count < 2:
    print_pm2()
    print_ps2()
    count += 1

print_pm2()
+ - - + - - +
|     |     |
|     |     |
+ - - + - - +
|     |     |
|     |     |
+ - - + - - +

grid2() 함수는 위 코드에 붙힌 이름에 불과하다.

위 코드의 또 하나의 핵심은 아래 두 변수가 가리키는 문자열을 격자무늬의 핵심 구성 단위로 사용한다는 점이다.

pm = "+ - - "
ps = "|     "

지금까지의 설명을 참고하면서 양의 정수 n이 주어졌을 때, n x n 모양의 격자무늬를 출력하는 grid() 함수를 구현해보자. 이를 위해 아래 두 아이디어를 활용한다.

  • 먼저 격자무늬의 기본 구성 단위는 pmps가 가리키는 문자열과 동일하다.

  • grid() 함수를 정의하기 위해 print_pm2() 함수와 print_ps2() 함수를 일반화한 아래 두 함수를 이용한다.

  • print_pm(n): n이 지정되면 pm을 그만큼 반복한다.

def print_pm(n):
    pm_line = pm * n + plus_sign
    print(pm_line)
  • print_ps(n): n이 지정되면 ps를 그만큼 반복한다.

def print_ps(n):
    ps_line = ps * n + pipe_sign
    print(ps_line, ps_line, sep="\n")

인자로 2를 사용하면 두 함수 각각 print_pm2() 함수와 print_ps2()함수와 동일한 결과를 낸다.

print_pm(2)
+ - - + - - +
print_ps(2)
|     |     |
|     |     |

반면에 4를 인자로 하면 오른쪽으로 보다 길어진다.

print_pm(4)
+ - - + - - + - - + - - +
print_ps(4)
|     |     |     |     |
|     |     |     |     |

즉 4칸짜리 격자무늬를 그리는 기초 구조로 활용될 수 있다. 두 함수를 연속 실행해보자.

print_pm(4)
print_ps(4)
+ - - + - - + - - + - - +
|     |     |     |     |
|     |     |     |     |

위 코드를 4번 반복하면 4 x 4 모양의 격자무늬가 거의 완성된다. 반복을 위해 역시 while 반복문을 활용하며, 따라서 grid() 함수는 grid2() 함수와 거의 동일하게 구현된다. 다만 함수의 본문에 사용되는 함수들 또한 일반화된 함수를 사용할 뿐이다.

def grid(n):
    count = 0
    while count < n:
        print_pm(n)
        print_ps(n)
        count += 1

    print_pm(n)
  • n = 3일 때

grid(3)
+ - - + - - + - - +
|     |     |     |
|     |     |     |
+ - - + - - + - - +
|     |     |     |
|     |     |     |
+ - - + - - + - - +
|     |     |     |
|     |     |     |
+ - - + - - + - - +
  • n = 4일 때

grid(4)
+ - - + - - + - - + - - +
|     |     |     |     |
|     |     |     |     |
+ - - + - - + - - + - - +
|     |     |     |     |
|     |     |     |     |
+ - - + - - + - - + - - +
|     |     |     |     |
|     |     |     |     |
+ - - + - - + - - + - - +
|     |     |     |     |
|     |     |     |     |
+ - - + - - + - - + - - +

지금까지 사용된 코드를 정리하면 아래와 같다. 결론적으로 이전 코드에서 숫자 2에 해당하는 부분을 모두 매개변수 n으로 대체하였을 뿐이다. 이처럼 함수의 일반화는 주로 기존 코드에서 특정 부분을 매개변수로 대체하는 과정을 따른다.

pm = "+ - - "
ps = "|     "
plus_sign = "+"
pipe_sign = "|"

def print_pm(n):
    print(pm * n + plus_sign)

def print_ps(n):
    ps_line = ps * n + pipe_sign
    print(ps_line, ps_line, sep="\n")

def grid(n):
    count = 0
    while count < n:
        print_pm(n)
        print_ps(n)
        count += 1

    print_pm(n)
  • n = 6일 때

grid(6)
+ - - + - - + - - + - - + - - + - - +
|     |     |     |     |     |     |
|     |     |     |     |     |     |
+ - - + - - + - - + - - + - - + - - +
|     |     |     |     |     |     |
|     |     |     |     |     |     |
+ - - + - - + - - + - - + - - + - - +
|     |     |     |     |     |     |
|     |     |     |     |     |     |
+ - - + - - + - - + - - + - - + - - +
|     |     |     |     |     |     |
|     |     |     |     |     |     |
+ - - + - - + - - + - - + - - + - - +
|     |     |     |     |     |     |
|     |     |     |     |     |     |
+ - - + - - + - - + - - + - - + - - +
|     |     |     |     |     |     |
|     |     |     |     |     |     |
+ - - + - - + - - + - - + - - + - - +

8.6연습문제

문제 3

아래 코드의 실행 결과를 설명하라. 반복문 실행횟수는 얼마인가?

def counter_func(num, limit) :
    i = 1
    while True :
        print(i)
        if i == limit :
            return i
        else:
            print("=" * i)
            print("*" * i)
            i += 1
        return num

counter_func(100, 5)
1
=
*
100

counter_func(100, 5)이 호출되면 함수의 본문이 차례대로 실행된다. i = 1 에서 시작하고 while True 반복문이 실행된다. 논리식 True가 참이라 while 반복문이 무한 반복되어야 하는 것처럼 보인다. print(i)에 의해 1이 출력되고 if ... else ... 조건문에서 i == limit가 거짓이기에 else의 본문이 실행되어 "=""*" 가 출력된다.

그런데 바로 이어서 return num 이 실행되어 100을 반환하고 반복문을 비롯해서 함수의 실행이 완전히 종료된다.