반복문

2023. 2. 27. 11:40Python/실전 예제로 배우는 파이썬 프로그래밍

반복문

특정 부분을 반복해서 실행하는 명령문으로 조건식이 참인 동안 특정 실행문이 반복적으로 수행되는 명령문으로 파이썬에서 while과 for 명령어로 제공됩니다.

 

while

조건식과 반복 실행문(loop)으로 블록을 구성합니다. 반복문을 수행하기 위해 조건부터 먼저 검사하기 때문에 반복의 대상인 실행문이 한 번도 수행되지 않습니다.

 

형식

While 조건식 :
              실행문1
                     :
              실행문n

 

실습 while 반복문 예시

# (1) 카운터와 누적변수
cnt = tot = 0	# 변수 초기화
while cnt < 5 :	# True : loop 수행
	cnt += 1	# 카운터 변수(cnt = cnt + 1)
    tot += cnt	# 누적변수 : tot = tot + cnt
    print(cnt, tot)
    
1 1
2 3
3 6
4 10
5 15

# [실습] 1 ~ 100 사이 3의 배수 합과 원수 추출하기
cnt = tot = 0
dataset = []	# 빈 list

while cnt < 100:	# 100회 반복
	cnt += 1	# 카운터
    if cnt % 3 == 0:
    	tot += cnt	# 누적변수
        dataset.append(cnt)	# cnt 추가

print('1 ~ 100 사이 3의 배수 합 = %d' % tot)
print('dataset =', dataset)

1 ~ 100 사이 3의 배수 합 = 1683
dataset = [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99]

# (1) 카운터와 누적변수

반복을 수행하는 과정에서 카운터 변수(cnt)는 정해진 상수값에 의해서 일정하게 값이 증가하는 변수를 의미하고, 누적 변수(tot)는 카운터 변수의 값을 차곡차곡 저장하는 변수를 의미합니다. 

 

# [실습] 1 ~ 100 사이 3의 배수 합과 원소 추출하기

카운터 변수(cnt)에 의해서 while 반복문은 100회 반복 수행됩니다. 이 과정에서 cnt 변수를 3으로 나누어서 나머지 값이 0이면 현재 cnt가 3의 배수이므로 빈 listfh 선언한 dataset에 cnt값을 추가(append)합니다.

 

실습 무한 루프(loop) 예시

# 무한 루프(loop)
numData = []	# 빈 list

while True :
	num = int(input("숫자 입력 : "))
    
    if num % 10 == 0 :	# exit 조건식
    	print("프로그램 종료")
        break
    else :
    	print(num)
        numData.append(num)	# list 추가

숫자 입력 : >? 11
숫자 입력 : >? 33
숫자 입력 : >? 55
숫자 입력 : >? 10 프로그램 종료

무한 루프(loop)는 반복문에서 사용되는 조건식이 True인 경우를 말합니다. 위 예문에서는 키보드로 임의의 숫자를 입력받아서 홀수이면 빈 list로 선언된 numData에 입력한 값이 원소로 추가되고, 루프가 반복됩니다. 한편 짝수가 입력되면 "프로그램 종료"라는 문자열이 출력되고, 루프에서 탈출됩니다.

 

random 모듈

컴퓨터에 의해서 임의 난수를 발생시키는 함수들을 제공합니다. 

 

random 모듈에서 제공하는 주요 함수와 기능

함수명 기능
choice(seq) 비어 있지 않은 sequence에서 임의의 요소를 선택한다.
choices(population, k) 모집단으로부터 k의 크기를 갖는 목록을 선택한다.
randint(a, b) [a, b] 범위에서 난수 정수를 반환한다.
random(...) 0~1 사이의 난수 실수를 반환한다. 
sample(population, k) 모집단(Population)으로 부터 k개를 임의 추출한다.
seed() 종자(seed) 값을 지정하여 동일한 난수가 선택되도록 한다.
uniform(a, b) [a, b] 범위의 난수 실수를 균등하게 반환한다.
normalvariate(mu, sigma) 정규 분포(Normal distribution)를 따르는 난수를 반환한다.(mu는 평균이고, sigma는 표준 편차를 의미한다.)

실습 random 관련 함수 1 예시

# (1) random module 추가
import random
help(random)	# 모듈 도움말

# (2) random모듈의 함수 도움말
help(random.random)

random() method of random.Random instance
random() -> x in the interval [0, 1).

#(3) 0~1 사이 난수 실수
r = random.random()
print('r=', r)	# r= 0.3940

r= 0.08630661167968179

# [실습] 난수 0.01 미만이면 종료 후 난수 개수 출력
cnt = 0
while True:
	r = random.random()
    print(random.random())
    if r < 0.01:
    	break	# loop exit
    else:
    	cnt += 1
print('난수 개수= ', cnt)

0.5884919679366538
0.6149177208255624
0.8133714205822925
0.5300546853873553
0.3308120316155594
0.48468831204914165
0.6672082410232629
0.5250513482026115
0.08818319312387013
0.3807964226411775
0.09131882021055737
0.8616398381316683
0.3132123356970775
0.6726968351103955
0.2052776621397986
0.6859636122513609
0.04200788444491166
0.3267834615157864
0.45102018746567507
0.17276901682942958
0.78928853477812
0.8115514513292039
0.9488931956923473
0.5178575274493249
0.22163028659342077
0.365589203485186
0.6242970396256043
0.18661152245057688
0.2523627429872054
0.9608853437993874
0.07854693345969033
0.30874865390168693
0.03073119912892086
난수 개수 =  32

# (1) random module 추가

random 관련 함수를 사용하기 위해서 import 명령으로 random 모듈(module)을 가져옵니다. 파이썬에서 모듈은 다수의 함수와 클래스를 포함하는 *. py 파일 형식으로 제공됩니다.

 

# (2) random모듈 관련 함수 도움말

random 모듈에서 제공되는 함수는 help(모듈명.함수명) 형식으로 도움말을 참고할 수 있습니다.

 

# (3) 0~1 사이 난수 실수

random 모듈에서 제공되는 random() 함수를 이용하여 0과 1 사이의 임의의 난수 실수를 반환한 결과입니다.

 

# [실습] 난수 0.01 미만이면 종료 후 난수 개수 출력

난수가 0.01 미만이면 반복을 출력(exit)하고, 그렇지 않으면 임의의 난수를 반복적으로 발생시켜서 출력하고, 카운트한 결과를 출력하는 예문입니다.

 

실습 random 관련 함수2 예시

# (1) random모듈 관련 함수 도움말
help(random.randint)
help(random.choices)	# 모집단에서 k 크기 목록 반환

randint(a, b) method of random.Random instance
    Return random integer in range [a, b], including both end points.
    
# (2) 이름 list에 전체 이름, 특정 이름 출력
names = ['홍길동', '이순신', '유관순']
print(names)	# 전체 이름
print(names[2])	# 특정 이름 출력

['홍길동', '이순신', '유관순']
유관순

# (3) list에서 자료 유무 확인하기
if '유관순' in names:
	print('유관순 있음')
else:
	print('유관순 없음')

유관순 있음

# (4) 난수 정수로 이름 선택하기
idx = random.randint(0, 2)
print(names[idx])

이순신

# (1) random모듈 관련 함수 도움말

randint와 choices 함수의 도움말을 참고합니다.

 

# (2) 이름 list에 전체 이름, 특정 이름 출력

여러 명의 이름을 갖는 names는 list형 자료구조를 갖는 변수입니다. list 자료구조는 여러 개의 원소를 1차원의 배열 형식으로 저장하며, names 변수를 출력하면 전체 원소가 출력되고, name [2]와 같이 색인(index)을 이용하면 3번째 원소의 이름이 출력됩니다.

 

# (3) list에서 자료 유무 확인하기

현재 names에는 '유관순' 원소를 포함하고 있기에 in을 사용할 수 있습니다.

 

# (4) 난수 정수로 이름 선택하기

randint(0, 2) 함수에 의해서 0~2 사이의 임의의 난수 정수가 반환됩니다. 이렇게 반환된 값을 색인으로 하여 names에서 해당 이름을 추출하는 예문입니다.

 

break, continue

break 명령어는 반복을 탈출(exit)하는 역할을 하고, continue는 다음에 오는 실행문을 실행하지 않고(skip) 반복을 지속하는 역할을 합니다.

 

실습 break, continue 예시

i = 0
while i < 10:
	i += 1	# 카운터
    if i == 3:
    	continue	# 다음 문자 skip
    if i == 6:	# 탈출 조건
    	break	# exit
    print(i, end='  ')
    
1 2 4 5

카운트 변수 i를 이용하여 조건식을 갖는 while 반복문은 정상적으로 10회 반복됩니다. 3이 출력되지 않은 이유는 'i == 3' 조건식에 의해서continue 다음에 오는 모든 실행문이 되지 않으므로 3은 출력되지 않고, 반복이 지속됩니다.

 

for

for 명령어를 이용한 반복문은 별도의 조건식이 없는 대신에 열거형객체를 이용합니다.

 

열거형 객체: 하나의 메모리 영역에 여러 개의 자료가 나열된 객체

 

for문의 in 뒤쪽에는 여러 개의 값을 가지고 있는 열거형 객체를 지정하고, in 앞쪽에는 열거형 객체의 값을 하나씩 넘겨받는 변수를 지정합니다. for 반복문에서 반복 횟수는 열거형 객체에 포함된 원소길이에 의해서 결정됩니다.

 

형식

for 변수 in 열거형객체 :
                   실행문1
                        :
                   실행문n

 

실습 for 반복문 예시

# (1) 문자열 열거형객체 이용
string = "홍길동"
print(len(string))	# 문자 길이 : 3
for s in string :	# 1문자 -> 변수 넘김 : 3회
	print(s)

3
홍
길
동

# (2) list 열거형객체 이용
lstset = [1, 2, 3, 4, 5]	# 5개 원소를 갖는 열거형객체

for e in lstset :
	print('원소 : ', e)

원소 :  1
원소 :  2
원소 :  3
원소 :  4
원소 :  5

# (1) 문자열 열거형객체 이용

string 변수는 3개의 문자로 구성된 열거형 객체입니다. for문에서 string을 열거형 객체로 사용하면 s 변수에 단일 문자가 1개씩 할당되면서 3회 반복됩니다.

 

# (2) list 열거형객체 이용

lstset 변수는 1에서 5까지 5개의 원소를 갖는 열거형 객체입니다. 5개의 원소가 순서대로 e 변수에 넘어오면서 5회 반복되어 원소가 출력됩니다.

 

for & range

파이썬의 모듈 파일(*. py)은 여러 가지 함수를 제공하기도 하지만 다양한 클래스를 제공하기도 합니다.

 

실습 range 클래스 예시

# (1) range 객체 생성
num1 = range(10)	# range(start)
print('num1 : ', num1)
num2 = range(1, 10)	# range(start, stop)
print('num2 : ', num2)
num3 = range(1, 10, 2)	# range(start, stop, step)
print('num3 :', num3)

num1 :  range(0, 10)
num2 :  range(1, 10)
num3 : range(1, 10, 2)

# (2) range 객체 활용
for n in num1 :
	print(n, end = ' ')
print()
for n in num2 :
	print(n, end = ' ')
print()
for n in num3 :
	print(n, end = ' ')

0 1 2 3 4 5 6 7 8 9 
1 2 3 4 5 6 7 8 9 
1 3 5 7 9

# (1) range 객체 생성

range 클래스를 이용하여 3가지 유형의 객체를 생성하고 있습니다.

 

# (2) range 객체 활용

range 클래스에 의해서 생성된 객체는 열거형 객체입니다. 따라서 for의 in 뒤에 열거형 객체로 이용할 수 있습니다.

 

for & list

배열(Array)은 자료를 순차적으로 저장하는 자료구조를 말합니다. 순차적으로 자료를 저장하고, 저장된 자료를 색인으로 참조할 수 있습니다.

# (1) list에 자료 저장하기
lst = []	# 빈 list 만들기
for i in range(10) :	# 0~9
	r = random.randint(1, 10)	# 난수 발생
    lst.append(r)	# 난수 저장


print('lst=', lst)	# 난수 출력

lst= [5, 9, 8, 7, 8, 2, 3, 3, 8, 4]

# (2) list에 자료 참조하기
for i in range(10) :	# 0~9
	print(lst[i] * 0.25)	# 난수 * 0.25
    
1.25
2.25
2.0
1.75
2.0
0.5
0.75
0.75
2.0
1.0

# (1) list에 자료 저장하기

range(10)에 의해서 0~9까지 10회 반복되면서 난수 정수 10개 생성됩니다. 이렇게 생성된 난수는 순차적으로 lst 변수에 저장됩니다.

 

# (2) range 객체 활용

색인을 이용하여 순차적으로 배열의 원소를 참조할 수 있습니다. 위 예문은 range(10)에 의해서 0~9까지 색인을 순서대로 발생시켜 10개의 난수에 각각 0.25를 곱해서 출력한 결과입니다.

 

중첩 반복문

중첩 반복문(이중 반복문)은 반복문 안에 또 다른 반복문이 포함된 명령문을 말합니다. 중첩 반복문은 for와 while 명령어 모두 사용이 가능한데, 바깥쪽 반복문과 안쪽 반복문의 영역은 들여 쓰기에 의해서 구분합니다.

단계 1 바깥쪽 반복문의 조건이 참(True)이면 1회 수행한 후 안쪽 반복문으로 진입한다.
단계 2 안쪽 반복문의 조건이 참(True)인 동안 반복한다.
단계 3 안쪽 반복문의 조건이 거짓(False)이면 안쪽 반복문을 탈출하고, 바깥쪽 반복문의 시작으로 이동하여 단계1 ~ 단계3을 반복 수행한다.

(1) 구구단

중첩 반복문의 수행과정에 따라 단은 바깥쪽 반복문에서 만들고, 곱해지는 수는 안쪽 반복문에서 만든 다음 단과 곱해지는 수를 곱해서 구구단을 만들 수 있습니다.

 

실습 구구단 예시

# 구구단 출력 : range() 함수 이용

# (1) 바깥쪽 반복문
for i in range(2, 10) :
	print('~~~ {}단 ~~~'.format(i))
    
    # (2) 안쪽 반복문
    for j in range(1, 10) :
    print('%d * %d = %d'%(i, j, i*j))

~~~ 2단 ~~~
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
2 * 5 = 10
2 * 6 = 12
2 * 7 = 14
2 * 8 = 16
2 * 9 = 18
~~~ 3단 ~~~
3 * 1 = 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
~~~ 4단 ~~~
4 * 1 = 4
4 * 2 = 8
4 * 3 = 12
4 * 4 = 16
4 * 5 = 20
4 * 6 = 24
4 * 7 = 28
4 * 8 = 32
4 * 9 = 36
~~~ 5단 ~~~
5 * 1 = 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
~~~ 6단 ~~~
6 * 1 = 6
6 * 2 = 12
6 * 3 = 18
6 * 4 = 24
6 * 5 = 30
6 * 6 = 36
6 * 7 = 42
6 * 8 = 48
6 * 9 = 54
~~~ 7단 ~~~
7 * 1 = 7
7 * 2 = 14
7 * 3 = 21
7 * 4 = 28
7 * 5 = 35
7 * 6 = 42
7 * 7 = 49
7 * 8 = 56
7 * 9 = 63
~~~ 8단 ~~~
8 * 1 = 8
8 * 2 = 16
8 * 3 = 24
8 * 4 = 32
8 * 5 = 40
8 * 6 = 48
8 * 7 = 56
8 * 8 = 64
8 * 9 = 72
~~~ 9단 ~~~
9 * 1 = 9
9 * 2 = 18
9 * 3 = 27
9 * 4 = 36
9 * 5 = 45
9 * 6 = 54
9 * 7 = 63
9 * 8 = 72
9 * 9 = 81

# (1) 바깥쪽 반복문

range(2, 10) 함수를 이용하여 2~9까지 단을 만들고, format() 함수를 이용하여 단을 출력합니다.

 

# (2) 안쪽 반복문

range(1, 10) 함수를 이용하여 1~9까지 곱해지는 수를 만들고, 단(i 변수)과 곱해지는 수(j 변수)를 곱해서 구구단을 계산하고, 출력합니다.

 

(2) 문장과 단어 추출

일반적으로 문단은 여러 개의 문장을 포함하고, 문장은 여러 개의 단어로 구성됩니다. 하나의 문단으로부터 문장과 단어를 추출하는 과정도 중첩 반복문을 이용할 수 있습니다.

string = """나는 홍길동 입니다.
주소는 서울시 입니다.
나이는 35세 입니다."""

sents = []	# 문장 저장
words = []	# 단어 저장

# (1) 문단 -> 문장
for sen in string.split(sep = "\n") :
	sents.append(sen)
    # (2) 문장 -> 단어
    for word in sen.split() :
    	words.append(word)

print('문장 :', sents)
print('문장수 :', len(sents))
print('단어 :', words)
print('단어수 :', len(words))

문장 : ['나는 홍길동 입니다.', '주소는 서울시 입니다.', '나이는 35세 입니다.']
문장수 : 3
단어 : ['나는', '홍길동', '입니다.', '주소는', '서울시', '입니다.', '나이는', '35세', '입니다.']
단어수 : 9

# (1) 문단 -> 문장

string 변수는 3줄의 문장으로 구성되어 있습니다. 따라서 줄 단위로 문장을 분리하기 위해서 string.split(sep = "\n") 명령문을 이용합니다. "\n" 기호에 의해서 줄 단위로 문자열이 분리되고, 순서대로 sents 변수에 추가됩니다.

 

# (2) 문장 -> 단어

바깥쪽 반복문에서 한 개의 문장(sen)을 받아서 sen.split() 명령문으로 단어를 추출합니다. split() 함수에서 sep 인자를 생략하면 기본적으로 공백을 기준으로 문자열이 분리됩니다. 분리된 단어는 words 변수에 순서대로 추가됩니다.