[처음 시작하는 파이썬] ch6. 반복문: while과 for 문

2023. 1. 21. 21:13파이썬/[처음 시작하는 파이썬] 개념

if, elif, else는 위에서부터 아래로 테스트를 실행합니다.

코드를 한 번 이상 실행하려고 할 때, 반복문(루프)이 필요한데,

파이썬은 두 개의 반복문 while for 문을 가지고 있습니다. 

 

6.1 반복하기: while

count = 1
while count <= 5:
    print(count)
    count += 1
1
2
3
4
5

위에서부터 순서대로 봐야합니다.

자, 우선 count 변수에 1을 할당했습니다.

while 문은 count 값이 5보다 작거나 같은지 계속 비교합니다. (할당하는 게 아니고 비교 연산자입니다.)

count <= 5가 True를 충족할 때 반복을 계속 하겠지요.

우선 count는 1로 할당 되어있으니 이는 5보다 작으니 프린트 함수가 출력되고

count값인 1이 출력이 됩니다.

출력 후에 count += 1 에 의하여 count 변수 값이 1씩 증가합니다.

count 값이 2가 된 상태에서 반복문은 맨 위로 올라가서 다시 비교를 시작합니다.

 

이 반복문은 언제까지 작동할까요? count <= 5가 False여야 멈출 테니까,

count가 6이 되면 while 문이 끝납니다.

그리고 다음 줄로 이동하여 진행됩니다.

 

6.1.1 중단하기: break

어떤 일이 일어날 때까지 반복하고 싶지만, 어떤 일이 언제 일어나는지 확실하지 않다면?

무한반복문에 break 문을 사용합니다.

 

input() 함수로 키보드에서 한 라인을 읽은 후 첫 번째 문자를 대문자로 출력하고,

문자 q를 입력하면 반복문을 종료하는 코드를 만들어 보려고 합니다.

 

while True:
    stuff = input("String to capitalize [type q to quit]:")
    if stuff == "q":
        break
    print(stuff.capitalize())
String to capitalize [type q to quit]:test
Test
String to capitalize [type q to quit]:hey, it works Hey, it works
Hey, it works hey, it works
String to capitalize[type q to quit]:q

자 True일 때 반복문 돌릴거고,

stuff 변수는 input. 입력값을 받습니다. 

만약에 입력값에 "q"를 받는다면, 반복문 탈출할 겁니다.

출력할 건데 stuff 입력값에 capitalize 적용해서 해줍니다.

 

while True:
    stuff = input("String to capitalize [type q to quit]:")
    print(stuff.capitalize())
    if stuff == "q":
        break
String to capitalize [type q to quit]:test
Test
String to capitalize [type q to quit]:hey, it works Hey, it works
Hey, it works hey, it works
String to capitalize[type q to quit]:q
Q

프린트의 위치가 중요한 게, 위에서 아래 순으로 작동한다는 것을 항상 인지해야합니다.

 

print가 break 문보다 위에 있다면 'q'를 입력했을 때 print가 우선되어서 'Q'가 먼저 출력이 되고

그 뒤 조건문 돌려봤을 때 'q'니까 멈추는 게 나중에 일어납니다.

 

우리가 원하는 건 'q'를 입력했을 때 완전히 종료하는 것이니, print를 break 문 뒤에 써줘야겠습니다.

 

6.1.2 건너뛰기: continue

반복문 중단하고 싶지 않지만, 반복을 건너 뛰어야 할 때가 있습니다.

 

정수가 홀수일 때는 그 수의 제곱을 출력하고, 짝수일 때는 다음 반복으로 건너뛰면서

q를 입력하면 반복문 종료를 한다고 할 때의 이 코드를 짜볼 겁니다.

 

while True:
    number = input('숫자를 입력해주세요. :')
    if int(number) % 2 == 1:
        print(number*number)
    elif int(number) % 2 == 0:
        continue
    elif number == 'q':
        break
print(number*number)
        ~~~~~~^~~~~~~
TypeError: can't multiply sequence by non-int of type 'str'

딱 처음에 이런식으로 짜봤어요.

근데 int타입이 아닌 거 끼리는 못 곱한다고 뜹니다..

 

근데 number 자체를 int로 바꾸면 문자열 'q' 못받으니까 break 못하잖아요..

 

input에는 문자열이랑 숫자 둘다 받을 수 있어야 하고..

 

그러려면 input 변수와 int 데이터타입 지정할 변수를 따로 지정해야 할 것 같습니다.

 

while True:
    value = input('숫자를 입력해주세요.[프로그램 종료 시 q입력] : ')
    if value == 'q':
        break
    number = int(value)
    if number % 2 == 0:
        continue
    print(number*number)

원하는대로 작동합니다.

value로 str,int 다 받아주다가 q로 원하는 처리가 끝나면 새로운 변수 만들어서 int 처리해줘서

나중엔 정수들만 받을 수 있겠군요!

 

그리고 여기서 continue 보면 if 문에서 true 충족하는 값은 (짝수) 그냥 넘어가 주겠다는 겁니다.

숫자를 입력해주세요.[프로그램 종료 시 q입력] : 2
숫자를 입력해주세요.[프로그램 종료 시 q입력] :

이렇게요. 짝수 입력하면 그냥 반복문 넘어가서 다시 반복됩니다.

이렇게 넘어가고 남은 조건들은 입력값이 짝수가 아닌 값인 것이겠죠?

 

짝수아닌 건 홀수고, 홀수인 값이 입력되면, print 문을 출력합니다.

숫자를 입력해주세요.[프로그램 종료 시 q입력] : 5
25

 

6.1.3 break 확인하기: else // break checker

break 문은 어떤 내용 확인하여 그것을 발견하면 종료하는 while 문을 작성할 때 사용합니다.

while 문이 모두 실행되었지만 발견하지 못했을 때는 else 문이 실행됩니다.

즉 break 문을 썼을 때 아무 것도 출력이 되지않는 상황입니다.

numbers = [1, 3, 5]
position = 0
while position < len(numbers):
    number = numbers[position]
    if number % 2 == 0:
        print('Found even number', number)
        break
    position += 1
 

아무것도 출력되지 않습니다. 짝수값이 확인안되어서 break가 작동하지 않고 끝났기 때문이지만,

while 문이 모든 항목을 잘 순회되었는지 확인하기는 어렵습니다.

 

그래서 break문에 의해 반복문이 중단되지 않고 모든 항목을 잘 순회했는지

확인해주는 느낌으로 쓰는 else 문입니다.

while 문이 끝난 뒤 써줍니다.

 

numbers = [1, 3, 5]
position = 0
while position < len(numbers):
    number = numbers[position]
    if number % 2 == 0:
        print('Found even number', number)
        break
    position += 1
else:
    print('No even number found')
No even number found
 
else문이 출력됩니다. while 문이 끝나고 작동합니다.
 
len(numbers)는 3 이잖아요?
position < len(numbers) 에서 반복한다는 의미이니까 position이 0 , 1 , 2일 때 즉 3번 반복한다는 겁니다. 
number = numbers[position] 해서 numbers 리스트 안에 있는 인덱스 순서를 나타내서
하나하나 조건과 비교할 수 있게 했습니다.
position += 1의 위치
 
 

position+=1은 positon=0에서 position=1,  position=2로 넘어가기 위해 써주는 건데,
이건 while문 안에 있으면서 if문 밖에 있어야 while문을 뜻대로 반복할 수 있게 됩니다.
 
IndexError: list index out of range

 

단, number = numbers[position] 전에 넣으면 인덱스에러가 납니다.

이해를 해보면, 

position < len(numbers) 에서 반복한다는 의미이니까 position이 0 , 1 , 2일 때 즉 3번 반복한다고 했습니다.
이게 position이 0,1일 때는 상관이 없어요. 바로 더해주면 각각 number = numbers[1],  number = numbers[2] 이
되어서 성립이 됩니다.
그러나 position 2일 때는, 와일문 들어가자마자 바로 1 더하면 number = numbers[3]이 되는데, 
numbers 안에 3인덱스가 가리키는 값은 없죠?
그래서 저 위치에 position+=1 해주면 안되는 겁니다. 에러가 납니다.
 
numbers = [1, 3, 5]
position = 0
while position < len(numbers):
    number = numbers[position]
    if number % 2 == 0:
        print('Found even number', number)
    else: print('No even number found')
    position += 1
No even number found
No even number found
No even number found

그리고 이렇게 while의 else 문이 아니라 break 안 쓰고 if문의 else으로 쓰면

출력이 numbers 리스트 안에 있는 값 하나하나에 적용되어 출력됩니다.

 

6.2 순회하기: for와 in

파이썬에서 이터레이터는 유용하게 자주 쓰입니다.

자료구조가 얼마나 큰지, 어떻게 구현되었는지에 관계없이 자료구조를 순회할 수 있게 해줍니다.

 

while문에 이어서 for문을 보겠습니다.

for문은 while문 사용보다 좀 더 파이써닉한 방법입니다.

 

words = 'thud'
offset = 0
while offset < len(words):
    word = words[offset]
    offset += 1
    print(word)
t
h
u
d

while문 사용

words = 'thud'
offset = 0

for letter in words:
    print(letter)
t
h
u
d

for문 사용

 

무슨 차이가 있냐면,

 

offset+=1이 필요가 없어집니다.

offset < len(words)같은 조건도 필요가 없어집니다.

 

for문 안에서 알아서 처음부터 끝까지 반복해줍니다.

 

6.2.1 중단하기: break

for 문의 break 문은 while 문의 break 문과 똑같이 동작합니다.

 

words = 'thud'
for letter in words:
    if letter == 'u':
        break
    print(letter)
t
h

'u'가 나오면 멈추는 for 문

break 한 뒤 print 하니까 'u'가 출력되지 않고 멈춥니다.

 

words = 'thud'
for letter in words:
    if letter == 'u':
        print(letter)
        break
    print(letter)
t
h
u

이렇게하면 u까지 출력되고 break 합니다.

 

6.2.2 건너뛰기: continue

while 문의 continue와 똑같이 동작합니다.

 

6.2.3 break 확인하기: else

while 문의 else 기능과 같습니다.

 

break 문에 의해 반복문이 중단되지 않고 모든 항목을 순회했는지 확인할 때 유용합니다.

 

words = 'thud'
for letter in words:
    if letter == 'x':
        print('x 발생')
        break
    print(letter)

else: print('x 없음')
t
h
u
d
x 없음

 

6.2.4 숫자 시퀀스 생성하기: range( )

리스트나 튜플 같은 자료구조 생성하여 저장하지 않더라도

특정 범위 내에서 숫자 스트림을 반환해줍니다.

 

이것은 컴퓨터의 메모리를 전부 사용하지 않고, 프로그램 충돌없이 아주 큰 범위를 생성할 수 있게 합니다.

 

range(start, stop, step) 형식입니다. 슬라이스 사용법과 비슷합니다.

 

start 기본값은 0

stop은 꼭 입력해줘야 하며, stop의 바로 직전 값까지 범위가 됩니다.

step 기본값은 1 입니다. step의 -1을 쓰면 역방향으로 진행됩니다.

 

순회가능한 객체를 반환하여 fot in 형태로 값을 순회할 수 있습니다.

 

for x in range(0, 3):
    print(x)
0
1
2

 

반환한 객체를 리스트와 같은 시퀀스로 변환할 수도 있습니다.

 

range()로 리스트 [0,1,2]를 만들어봅시다.

 

print(list(range(0,3)))
[0, 1, 2]

 

거꾸로 진행하는 2에서 0의 리스트를 만들어봅시다.

print(list(range(2, -1, -1)))

for x in range(2, -1, -1):
    print(x)
[2, 1, 0]

2
1
0
 

다음은 0에서 10까지 2씩 진행하는 짝수 리스트를 만들어봅시다.

print(list(range(0, 11, 2)))

for x in range(0, 11, 2):
    print(x)
[0, 2, 4, 6, 8, 10]

0
2
4
6
8
10