━━━━ ◇ ━━━━
따라하며 배우는 파이썬과 데이터 과학/PART 1. 파이썬 기초체력 다지기

Chapter 05. 여러 번 반복하는 일을 하자

이번 시간의 목차

1. 반복문이 뭐길래?

2. 정해진 횟수만큼 반복하자! for문

3. for문과 range() 함수는 천생연분!

4. 조건에 따라 반복하자! while문

5. 무한 루프를 제어해 보자, break와 continue!

6. 들쭉날쭉한 글씨는 포매팅으로 다듬자!

7. 마무리

 

 

자, 가자! 파이썬의 세계로!


 

반복문이 뭐길래?

 

 반복문이란 어떤 단계를 반복하게 하는 것으로, 반복문이 없다면 똑같은 문장을 여러 번 출력하고 싶을 때 Ctrl+c 후 Ctrl+v를 많이 써야 하는 불편함이 있고, 그렇게 똑같은 문장을 여러 번 쓰다 보면 보기에도 깔끔하지 않다. 반면, 반복 구조를 사용하면 반복적으로 수행하는 번거로운 작업을 간결하게 만들어 준다. 따라서반복문은 매우 중요한 제어문으로 쓰인다. 

 

 파이썬에는 두 가지 종류의 반복문이 있다. 

  • 횟수 제어 반복(for 문) : 횟수를 정해 놓고 반복한다.
  • 조건 제어 반복(while 문) : 특정한 조건이 만족되면 계속 반복한다.

 

 

 횟수 제어 반복은 반복할 횟수를 미리 아는 경우에 사용한다. 횟수는 꼭 숫자로만 이루어질 필요는 없고, 시퀀스(Sequence)를 가져와서 반복할 수도 있다. 시퀀스 자료형에는 리스트, 튜플, range, 문자열 등 값이 연속적으로 이어진 자료형이다. 시퀀스에 항목이 더 이상 없으면 반복이 종료된다. 예시로 든 range(5)라는 함수는 0, 1, 2, 3, 4의 숫자 시퀀스를 생성하는 함수로, for i in range(5)는 0에서 4까지의 숫자를 반환하는 작업을 끝낼 때까지 반복 실행된다. 

 

 조건 제어 반복은 조건에 따라 반복할 경우에 사용한다. 조건식은 이전 시간에 다루었듯이 최종적으로 True 또는 False 값을 가지는 문장이면 된다. 오른쪽에서 예시로 든 i = 0과 i < 5, i = i + 1은 i가 0으로 시작해서 블록을 반복할 때마다 'Hello Python!!'을 출력하고 i가 1씩 늘어나, 결국 i가 5 이상이 되면 반복을 멈추게 된다. 

 

 이런 반복을 프로그래밍에서는 흔히 동그란 고리를 의미하는 루프(Loop)라고도 한다. 프로그램이 반복해서 이전 단계로 돌아가는 모습이 동그라미를 그리는 것 같기 때문이다. 이 고리를 빠져나오지 않고 계속해서 반복하면 무한루프(Infinite Loop)라고 한다. 

 


 

정해진 횟수만큼 반복하자! for문

 

 for 루프는 반복할 횟수를 정해 두고, 이 횟수가 만족될 때까지 같은 동작을 반복한다. 우선 for 루프의 시퀀스로 리스트를 이용해 보자. 리스트는 대괄호 [...] 로 둘러싸인 값들인데, 이것은 7장에서 더 자세히 다룰 것이다. 지금은 고등학교 수학 시간에 배우는 집합과 비슷한 것이라고 이해하고 넘어가자. 

 

>>> for i in [12345] :
    print('즐거운 파이썬!')
 
    
즐거운 파이썬!
즐거운 파이썬!
즐거운 파이썬!
즐거운 파이썬!
즐거운 파이썬!
cs

 

 반복문의 끝에는 if문과 마찬가지로 콜론이 있어야 하고, 한 블록 안에는 무조건 들여쓰기가 똑같은 공백 수만큼 되어 있어야 한다. 위 코드에서 print('즐거운 파이썬!') 문장은 리스트에 있는 데이터의 개수만큼 반복된다. 반복되는 상황을 좀 더 자세히 볼까? 이번에는 print() 함수로 변수 i의 값도 확인해 보자.

 

>>> for i in [12345] :
    print('지금은', i, '가 반복할 차례!')
 
    
지금은 1 가 반복할 차례!
지금은 2 가 반복할 차례!
지금은 3 가 반복할 차례!
지금은 4 가 반복할 차례!
지금은 5 가 반복할 차례!
cs

 이렇게 시퀀스에 든 모든 항목의 차례가 지나면 반복이 종료된다. 

이번에는 시퀀스에 리스트가 아닌 문자열을 넣어보자. 

 

>>> for i in 'Apple' :
    print('지금은', i, '가 반복할 차례!')
 
    
지금은 A 가 반복할 차례!
지금은 p 가 반복할 차례!
지금은 p 가 반복할 차례!
지금은 l 가 반복할 차례!
지금은 e 가 반복할 차례!
cs

 똑같이 시퀀스에 든 모든 항목의 차례가 지나면 반복이 끝난다. 

조금 더 응용하면 이렇게 구구단도 만들 수 있다. 

 

>>> for i in [12345] :
    print('9 *', i, '='9 * i)
 
    
9 * 1 = 9
9 * 2 = 18
9 * 3 = 27
9 * 4 = 36
9 * 5 = 45
cs

 

for문과 range() 함수는 천생연분!

 

  방금은 리스트에 정수를 저장해두고 하나씩 꺼내 썼지만, 반복 횟수가 많아진다면 일일이 저장하고 꺼내 쓸 수 없다. 이런 때에는 range() 함수를 사용하면 편하다. 앞서 설명했듯, range(start, stop, step)은 start에서 시작하여 (stop - 1)까지 step 간격으로 정수들이 생성된다. start와 step 값은 생략할 수 있고, 생략할 경우 start는 0, step은 1로 간주된다. stop 값은 반드시 지정해야 한다.

 

 이해가 잘 되지 않으면 실제로 한 번 해 보자.

 

>>> for i in range(5) :    #0부터 4까지의 range
    print(i, end = ' ')    #end = ' '는 줄바꿈 대신 공백을 넣는다.
 
    
0 1 2 3 4 
>>> for i in range(18) : #1부터 7까지의 range
    print(i, end = ' ')
 
    
1 2 3 4 5 6 7 
>>> for i in range (0112) : #0부터 10까지 2씩 건너 뛴 range
    print(i, end = ' ')
 
    
0 2 4 6 8 10 
cs

 

 만약 10에서부터 1까지 1씩 감소하며 반복하고 싶다면 range(10, 0, -1)을 써 주면 된다.

 

>>> for i in range(100-1) :
    print(i, end = ' ')
 
    
10 9 8 7 6 5 4 3 2 1 
cs

 


 

조건에 따라 반복하자! while문

 

  조건 제어 반복은 어떤 조건이 만족되는 동안 반복하기 때문에 붙여진 이름이다. 반복되는 횟수를 알 수 없거나, 특별한 조건이 필요할 때에 쓰인다. 예시로 컴퓨터 사용을 위해 패스워드를 입력해야 한다고 하자. 입력한 패스워드가 미리 설정해둔 값과 일치하지 않는다면 일치할 때까지 입력을 요구해야 할 것이다. 

 

password = ''
while password == 'mycomputer' :
    password = input('암호를 입력하시오: ')
 
print('환영합니다.')
 
 
cs

 if문과 마찬가지로 while문에도 콜론이 붙고, 한 블록에는 동일한 공백 수만큼의 들여쓰기가 들어간다. 

 

 횟수 제어 반복문이 있다고 해서 while에는 횟수를 써먹을 수 없는 걸까? 아니다. 횟수를 알고 있는 경우에도 while 루프를 사용할 수 있다. 예를 들어 1부터 10까지의 합을 계산하는 코드를 while 루프로 작성해보자. 1부터 10까지 늘어나는 변수 count를 1로 초기화하여 만들고 합을 저장할 변수 s를 0으로 초기화하자. 

 

count = 1
= 0                  #1부터 10까지의 합은 여기에 저장된다. 
while count <= 10 : 
    s = s + count      #매번 count 값을 s에 저장해 더한다.
    count = count + 1  #count 값을 1 늘린다. 
 
print('합계는', s)
cs

 

이 코드의 count와 s값의 변화, 그리고 count <= 10 조건문의 반환값은 아래와 같다. 

count s count <= 10 반복 여부
1 1 True 반복
2 1 + 2 True 반복
3 1 + 2 + 3 True 반복
4 1 + 2 + 3 + 4 True 반복
5 1 + 2 + 3 + 4 + 5 True 반복
6 1 + 2 + 3 + 4 + 5 + 6 True 반복
7 1 + 2 + 3 + 4 + 5 + 6 + 7 True 반복
8 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 True 반복
9 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 True 반복
10 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 True 반복
11 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 False 반복 중단

 

 count가 11이 되면 count <= 10 이라는 조건에 어긋나므로 반복이 중단되는 것을 볼 수 있다. 


 

무한 루프를 제어해 보자, break와 continue!

 

  조건 제어 루프에서 프로그램이 무한히 반복하는 일을 무한 루프라고 이미 소개한 바 있다. 이 무한 루프는 말 그대로 빠져 나올 수 없기 때문에 어떤 때에는 문제라면 문제가 된다. 

 

 이런 무한 루프에서 빠져나오려면 이 키워드를 꼭 기억해야 한다. break. 루프를 강제적으로 빠져나올 때 사용하는 문장이다. 사용법의 간단한 예를 들자면 아래와 같다.

 

while True :
    light = input('신호등 색상을 입력하시오: ')
    if light == 'green' :
        break
 
print('전진!')
cs
신호등 색상을 입력하시오 : red
신호등 색상을 입력하시오 : yellow
신호등 색상을 입력하시오 : green
전진!!
cs

 

 이 코드에서는 '신호등 색상을 입력하시오: '를 출력하고 사용자의 입력을 기다린다. while True : 로 설정하면 항상 참이기 때문에 무한 반복이 이루어진다. 사용자가 'green'을 입력하면 break 문장을 실행해서 루프를 빠져나가고 '전진!!' 이 출력되는 것이다. 

 

 continue는 루프를 빠져나오지 않고 아래의 문장만을 건너뛰는 역할을 한다. 즉 반복문이 종료되는 것은 조건이 거짓일 때에만 해당된다. continue도 간단한 예시를 통해 사용법을 알아보자.

 

>>> st = 'I love Python Programming'
>>> for ch in st :
        if ch in ['a','e','i','o','u''A','E','I','O','U'] :
            continue
        print(ch, end='')
 
    
 lv Pythn Prgrmmng
cs

 

 'I love Python Programming'이라는 문자열 내에서 반복하여 모음이 반복할 차례가 오면 continue를 통해 아래 문장을 생략하고 다음 반복으로 넘어가서 자음이나 공백이 출력된다. 

 

 continue와 break는 잘 활용하면 편리한 프로그램을 만들 수 있겠지만, 너무 많이 쓰면 제어의 흐름에 일관성이 없어지기 때문에 코드를 읽기 어려워진다. 따라서 continue와 break는 필요한 경우에만 제한적으로 쓰는 것이 좋다. 

 


 

들쭉날쭉한 글씨는 포매팅으로 다듬자!

 

  지금까지 print()를 이용하여 다양한 출력을 해 보았는데, 출력을 다듬지 않아 출력 메세지의 간격이 들쭉날쭉했다. 

문자열을 가지런하게 정리하려면 format() 메소드를 사용하면 된다. 플레이스홀더 {}로 format() 메소드의 인자로 들어오는 값이 출력될 위치를 지정한다. 

 

>>> '{} Pyhon!'.format('Hello')
'Hello Pyhon!'
>>> 'I like {0} and {1}'.format('Python''Java')
'I like Python and Java'
>>> 'I like {0} and {0}'.format('Python''Java')
'I like Python and Python'
cs

 

 format() 메소드의 인자에 부여된 0, 1과 같은 인덱스를 이용하여 인자값을 지정할 수도 있다. 인덱스에 대해서는 7장 리스트 부분에서 자세하게 설명한다.

 

 부동소수점(Floating Point)을 이용하면 소숫점 아래 n번째 숫자를 출력할 수도 있다. 부동소수점으로는 f를 사용한다. 

 

>>> '소수점 아래 두자리 정밀도 : {0:.2f}, 세자리 정밀도 {0:.3f}'.format(1/3)
'소수점 아래 두자리 정밀도 : 0.33, 세자리 정밀도 0.333'
>>> '전체 10칸을 차지하는 실수 : {0:10.2f}, {0:10.3f}'.format(3.1415926)
'전체 10칸을 차지하는 실수 :       3.14,      3.142'
cs

 

 여기서 {0:.nf}는 format() 메소드의 인자를 소숫점 아래 n자리까지 표시해주고, {0:m.nf}는 전체 m칸을 차지하는 데에서 소숫점 n자리만큼을 채워 출력해준다. 예로 사용된 {0:10.2f}는 전체 10칸에서 소숫점 2자리까지를 포함하여 가장 오른쪽에 소수를 써 주고, 앞의 남은 6칸은 공백으로 채운다.

 

 또 정수를 깔끔하게 써주려면 {i:nd}의 형태로 포매팅을 해 주면 된다.

 

>>> for i in range(2112) :
    print('{0:3d} {1:4d} {2:5d}'.format(i, i*i, i*i*i))
 
    
  2    4     8
  4   16    64
  6   36   216
  8   64   512
 10  100  1000
cs

 

 이때 i에는 format() 메소드의 인자의 인덱스, n에는 전체 몇 칸이 사용될지를 써 준다.


 

마무리

 

  이번 시간에는 횟수 또는 조건에 따라 프로그램을 반복해서 수행시키는 for문과 while문에 대해 알아보았다.

마지막으로 도전문제 5.7, 5.8-(3), 5.12, 심화문제 5.2, 5.5, 5.8을 풀어보고 마치도록 하자. 접은글 속의 해답 코드는 참고만 하자.

 

도전문제

 

5.7: 구구단의 1단부터 9단까지를 모두 출력하도록 아래의 코드를 수정해보자.

dan = int(input('원하는 단은: '))
= 1
 
while i <= 9 :
    print('{} * {} = {}'.format(dan, i, dan * i))
    i = i + 1
cs
더보기
for n in range (110) :
    i = 1
    while i <= 9 : 
        print('{} * {} = {}'.format(n, i, n * i))
        i = i + 1
cs

 

 

5.8-(3): 아래의 코드를 이용하여 그림과 같은 별모양을 그려 봐라. 한 각은 그림을 참고하여라.

import turtle
= turtle.Turtle()
t.shape('turtle')
= 0
while i < 5:
    t.forward(50)
    t.right(144)
    i = i + 1
cs
더보기
import turtle
= turtle.Turtle()
t.shape("turtle")
= 1   #변의 개수 
= 1   #별의 팔 개수 
 
while i <= 10:
    t.forward(50)
    if i == d * 2 - 1 :  #홀수 번째 변을 그리고 나서 왼쪽으로 72도 돈다. 
        t.left(72)
        i = i + 1
 
    elif i == d * 2 :    #짝수 번째 변을 그리고 나서 오른쪽으로 144도 돈다.
        t.right(144)
        i = i + 1
        d = d + 1
 
cs

 

 

5.12: 사용자로부터 하나의 단어를 입력받은 다음 이 단어에서 모음이 나타나기 전까지의 모든 자음을 출력하는 프로그램을 작성하여라. 예를 들어 다음과 같이 'programming'이 입력되면 'o'가 나타나기 이전인 pr만 출력하도록 하여라. 

단어를 입력하세요 : programming
pr
cs
더보기
word = input('단어를 입력하세요 : ')
= ['a''e''i''o''u''A''E''I''O''U'#모음 리스트
 
for i in word :
    if i in W :   # in은 앞의 데이터가 뒤의 시퀀스에 들어 있는지 참/거짓으로 판단한다.
        break
    print(i, end = ''#들어있지 않으면 출력
 
cs

 

 

 

심화문제

 

5.2: 반복문을 활용하여 특정 구간의 수의 합을 구할 수 있다. 

1) for 반복문과 while 반복문을 사용하여 1에서 100까지의 정수 중에서 홀수의 합을 출력하는 프로그램을 작성하여라.

1에서 100까지의 수 중에서 홀수의 합 : 2500
cs
더보기
= 0      #숫자의 합을 저장할 변수를 선언한다. 
for i in range (11012) : 
    S = S + i  #1에서 2씩 건너뛰어 100까지의 홀수를 더해나간다.
 
print('1에서 100까지의 수 중에서 홀수의 합 : ', S)
cs

 

2) for 반복문과 while 반복문을 사용하여 1에서 100까지의 정수 중에서 짝수의 합을 출력하는 프로그램을 작성하여라.

1에서 100까지의 수 중에서 짝수의 합 : 2550
cs
더보기
= 0
for i in range(01012) :
    S = S + i
 
print('1에서 100까지의 수 중에서 짝수의 합 : ', S)
cs

 

3) 사용자로부터 시작 정수와 끝 정수를 입력으로 받은 다음 시작 정수 값에서 끝 값까지의 합을 구하여 다음과 같이 출력하는 프로그램을 작성하여라. 

시작 정수를 입력하세요 : 2
끝 정수를 입력하세요 : 6
2 에서 6 까지 정수의 합 : 20
cs
더보기
start = int(input('시작 정수를 입력하세요 : '))
end = int(input('끝 정수를 입력하세요 : '))
= 0
 
for i in range(start, end + 1) :
    S = S + i
 
print(start, '에서', end, '까지 정수의 합 : ', S)
 
cs

 

 

5.5 : 깊이가 30 미터인 우물이 있다. 이 우물에 사는 달팽이는 하루 종일 기어서 올라가면 7미터를 올라갈 수 있다. 그러나 밤이 되어 휴식을 취하는 동안 5 미터를 미끄러져 내려간다. 이 우물을 벗어나는데 며칠의 시간이 걸릴까? while문을 이용하여 매일 저녁 달팽이의 위치를 다음과 같이 구하시오. 출력 시 format() 메소드를 이용하여 숫자들이 오른쪽 정렬되도록 하자. (주의! 하루에 7 - 5 = 2미터를 올라갈 것이라고 단순 계산하면 안 된다. 이 경우 15일 되는 날 탈출하는 것으로 계산되지만 실제로는 13일이면 된다.) 

day :   1 달팽이의 위치 :   7 미터
day :   2 달팽이의 위치 :   9 미터
day :   3 달팽이의 위치 :  11 미터
day :   4 달팽이의 위치 :  13 미터
day :   5 달팽이의 위치 :  15 미터
day :   6 달팽이의 위치 :  17 미터
day :   7 달팽이의 위치 :  19 미터
day :   8 달팽이의 위치 :  21 미터
day :   9 달팽이의 위치 :  23 미터
day :  10 달팽이의 위치 :  25 미터
day :  11 달팽이의 위치 :  27 미터
day :  12 달팽이의 위치 :  29 미터
day :  13 달팽이의 위치 :  31 미터
축하합니다. 우물을 탈출하였습니다.
우물을 탈출하는 데 걸린 날은  13 일 입니다.
cs
더보기
day = 0
Posit = 0
 
while Posit <= 30 :      #위치가 30m 이하이면 아래가 반복된다. 
    day = day + 1        #하루가 시작되고 
    Posit = Posit + 7    #현재 위치에서 7m를 올라간다.
    print('day :''{0:3d}'.format(day), '달팽이의 위치 :''{0:3d}'.format(Posit), '미터')
 
    if Posit <= 30 :       #7m를 올라가도 30m 이하라면 
        Posit = Posit - 5  #저녁동안 5m 내려간다. 
 
    elif Posit >= 30 :
        print("축하합니다. 우물을 탈출하였습니다.")
        print("우물을 탈출하는 데 걸린 날은 ", day, "일 입니다.")
 
cs

 

 

5.8 : 거꾸로 정수는 121이나 3443과 같이 거꾸로 나열해도 그 값이 원래의 값과 같은 정수를 말한다. 사용자로부터 임의의 양의 정수를 입력받아 이 수가 거꾸로 정수인지 아닌지를 판단하는 다음과 같은 프로그램을 작성하시오. 입력을 받을 때 -99가 들어올 경우 더 이상 입력을 받지 않는다.

정수를 입력하시오 : 3443
3443 은(는) 거꾸로 정수입니다.
정수를 입력하시오 : 324
324 은(는) 거꾸로 정수가 아닙니다.
정수를 입력하시오 : -99
프로그램을 종료합니다.
cs
더보기
n1 = 0     #루프 돌입 전 입력 받을 정수를 초기화시킨다. 
 
while n1 != -99 :   #-99가 입력될 때까지 반복한다. 
    n1 = int(input("정수를 입력하시오 : "))
    n = n1
    N = 0           #입력받은 정수를 뒤집은 것이 들어갈 변수 초기화 
    
    while n > 0 :
        N = N * 10 + n % 10  
        n = n // 10
 
#위 블록을 343으로 예를 들어보자.
#루프 돌입 전 : n = 343, N = 0
#루프 1회 : n = 343 // 10 = 34, N = 0 + 3 = 3
#루프 2회 : n = 34 // 10 = 3, N = 3 * 10 + 34 % 10 = 34
#루프 3회 : n = 3 // 10 = 0, N = 34 * 10 + 3 % 10 = 343
#n < 0이므로 루프를 종료. N은 n1을 뒤집은 수가 된다. 
    
    if n1 == N :
        print(n1, "은(는) 거꾸로 정수입니다.")
 
    elif n1 == -99 :
        break
 
    elif n1 != N :
        print(n1, "은(는) 거꾸로 정수가 아닙니다.")
 
 
print("프로그램을 종료합니다.")
 
cs
COMMENT