파이썬을 배워보자 9일차 - 반복문(while, for)

0

Python

목록 보기
9/18

점프 투 파이썬 : https://wikidocs.net/book/1
파이썬 기본을 갈고 닦자 : https://wikidocs.net/16031

반복문

보통 대부분의 언어가 반복문으로 for, while이 있다. (go는 for문만 있다) 파이썬 역시도 for, while로 구성되어있으므로 하나씩 알아보자.

1. while문

반복해서 문장을 수행할 때, 반복문을 사용한다. 이 while문은 다음과 같은 구조를 갖는다.

while 조건:
    본문
    본문

while조건이 참인 경우에만 반복문을 수행한다. 즉, 조건이 거짓이 되면 반복문 수행을 종료한다. 그렇다고 반복되는 와중에 갑자기 종료된다는 것이 아니라, 조건을 검사했을 때 False이면 종료한다는 것이다.

count = 0
while count < 10:
    count += 1
    if count == 5:
        count = 10
    print(count) # 1 2 3 4 10

print(count) # 10

다음의 반복문을 보면 count가 10이하이면 반복해서 count을 하나씩 더하고 while문을 반복한다. 즉 다음의 순서로 반복한다는 것이다.

  1. while문 조건인 count가 10보다 작은가??
    1. 그렇다면 while의 본문으로 들어간다.
    2. count가 하나 더해진다.
    3. count가 5와 같은 지 확인을 한다.
      1. count가 5와 같으면 count는 10이 된다.
    4. print이 실행되어 count값이 찍힌다.
    5. 다시 1로 돌아간다.
  2. 만약 count가 10보다 작지 않다면 while문을 종료한다.

이 때 if문에 의해서 count가 5가 되면 count를 10으로 채운다.

여기서, count가 10보다 작지 않고, 같으므로 while문이 뙇 종료되는 것이 아니다. 이 증거로 print문이 if문다음인데 10을 프린트한 것을 보면 알 수 있다.

즉, 반복문이 종료되는 것은 본문에서 조건문의 변수를 아무리 바꾸어 종료조건이 성립되도 반복문이 자신의 조건을 검사할 차례 때까지 본문을 실행한다.

물론 break를 사용하면 원하는 위치에서 while문을 종료시킬 수 있는데 이는 뒤에 배운다.

2. break, continue문

break문은 while문 뿐만 아니라, for문과 같은 반복문에도 쓰일 수 있다. 이를 이용하면 본문이 구동될 때 특정한 조건이 성립하는 경우 반복문을 종료할 수 있다.

count = 0
while count < 10:
    count += 1
    if count == 5:
        count = 10
        break
    print(count) # 1 2 3 4

print(count) # 10

다음의 코드는 위의 코드에서 if count == 5이면 count = 10을 하고 break시키는 코드이다. 이전에는 while문의 조건문까지 돌아야 count의 값이 10임으로 알고 종료되었는데, break를 사용하면 즉시 반복문이 종료된다.

이에 따라, count = 10일 때 본문의 print문이 실행되지 않고, 반복문을 종료하기 때문에 결과로 1 2 3 4만 나오고, 반복문을 종료한 print에서 10이 나온다.

그러나 만약, 반복은 하되 특정 부분은 처리하고 싶지 않을 때는 어떻게 해야할까? 종료시키고 또 반복문을 돌게하면 너무 비효율적이다. 그래서 continue를 사용한다.

continue가 작동하면, 반복문의 본문 구동을 중단하고 다음 라운드로 넘어간다. 여기서 다음 라운드라는 것은 반복문의 조건을 말한다. 즉, 남은 본문 부분은 실행하지않고 조건부분으로 간다는 것이다.

count = 0
while count < 10:
    count += 1
    if count % 2 == 0: continue
    print(count) # 1 3 5 7 9

print(count) # 10

다음과 같이 count는 반복문을 순회할 때 하나씩 더해진다. 이 때 if문에서 count % 2 == 0 을 만나면 count가 짝수인 경우는 다음 반복문으로 넘어가게 된다.

그렇게 되면 다시 반복문의 나머지 본문인 print를 넘기게 되고, while의 조건쪽으로 넘어가게 된다.

이에 따라, count는 짝수인 경우를 print하지않고 넘어가며 count를 하나씩 추가한다. 그리고 while문의 조건부를 계속검사하며 마침내 count10이 되는 순간 종료한다.

3. for문

사실 while문 보다 많이 사용되는 반복문이 바로 for문이다.

for문은 while문보다 사용하기 쉽고, 여러기능을 제공한다.

기본구조는 다음과 같다.

for 변수 in iterable:
    본문1
    본문2
    ...

여기서 iterable리스트, 튜플, 문자열을 말하며 첫번째 요소부터 마지막 요소까지 가져온다. 그리고 이 요소들은 매 라운드마다 변수에 할당되는 것이다.

values = [123, 124, 643, 0]
for value in values:
    print(value) # 123 124 643 0

이 처럼, 리스트안에 있는 요소들이 value에 매 라운드마다 들어가는 것이다. 리스트의 마지막 요소까지 반복하고 종료한다.

리스트안에 튜플이 있는 경우, 다음과 같이 요소들을 가져올 수도 있다.

a = [(1,2), (3,4) , (5, 6)]
for first, second in a:
    print(first, second) # 1 2 , 3 4 , 5 6

리스트 안에 있는 요소가 튜플인 경우, 튜플안의 값들을 변수에 각각 할당할 수 있다. 마치 자바스크립트의 비구조화 할당과 같은 개념으로 튜플이 이런게 가능했다는 것은 이전에도 확인했다.

그럼 매번 반복할 때마다, 원하느 값들을 리스트로 만들어서 주어야 할까?? 이건 사실 조금 불편하다. 그래서 range라는 것이있다.

3.1 range

정수 0에서부터 10까지의 수를 만든다고하자, 다음처럼 일일히 만들어주는 것은 매우불편한 일이다.

count = 0
values = []
while count < 10:
    values.append(count)
    count += 1

print(values) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

다음의 코드는 너무 복잡하고, 귀찮다. 그래서 우리는 range()를 사용하도록 하자, range를 사용하면 특정 범위의 정수값을 생성하여 iterable한 range객체로 돌려준다.

사용방법은 다음과 같다.

range(end) # 0~end-1까지 정수생성
range(start, end) # start부터 end-1까지 정수생성
range(start, end, step) # start부터 end-1까지 정수를 생성하되 step만큼 증가

range객체를 in과 함께쓰면 range객체가 iterable하므로 for문을 통해 element를 하나씩 가져올 수 있다.

for elem in range(10):
    print(elem, end=" ") # 0 1 2 3 4 5 6 7 8 9 

바로 이렇게 말이다. 참고로 print(elem, end=" ")라고 쓰면 출력하는 마지막에 공백을 추가한다. 기본적으로 개행문자인 \n으로 되어있어 한줄을 띄게되는 것이다.

다음과 같이 다양하게 사용할 수 있다.

for elem in range(10):
    print(elem, end=" ") # 0 1 2 3 4 5 6 7 8 9 

for elem in range(5,10):
    print(elem, end=" ") # 5 6 7 8 9

for elem in range(5,10, 2):
    print(elem, end=" ") # 5 7 9

조심할 것은 range의 경우 end값은 포함하지 않는다는 것이다. 즉, 마지막 값은 포함하지 않으므로 end-1까지라고 쓴 것이다.

3.2 break, continue

for문 역시도 breakcontinue를 사용할 수 있다.

for elem in range(10):
    if elem == 5:
        break
    print(elem) # 0 1 2 3 4

print(elem) # 5

for문이 계속 순회하여 print를 만나 0 1 2 3 4를 출력하게 된다. 여기서 elem == 5를 만나면 break되어 순회를 종료하게 된다.

마찬가지로 continue를 쓰면 해당 라운드만 넘기고 다음 라운드로 간다.

for elem in range(10):
    if elem == 5:
        continue
    print(elem) # 0 1 2 3 4 6 7 8 9

print(elem) # 9

다음의 결과를 보면 elem5일 때만 쏙 빠진 것을 확인할 수 있다. 이를 통해 for문에서 continue가 잘 작동하는 것을 확인할 수 있다.

4. 리스트 내포(list comprehension) 사용하기

리스트 안에 for문을 포함하는 리스트 내포(list comprehension)을 사용하면 좀 더 편리하고 직관적인 프로그램을 만들 수 있다.

사용 방법은 다음과 같다.

result = [본문 for elem in iterable]

위에서 range를 사용하여 0~9까지의 값을 만들었다면, 이를 이용하여 list에 값을 넣어보도록 하자

result = []
for elem in range(10):
    result.append(elem)

print(result) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

이를 리스트 내포(list comprehension)을 사용하여 표현해보자

result = [elem for elem in range(10)]
print(result) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

훨씬 코드가 단순해졌다. 솔직히 쉬운지는 잘 모르겠으나 일단 간단해보이긴한다.

그러나, 만약 짝수를 거르고 홀수만 담고 싶다면 어떻게해야할까?? 재밌게도 리스트 내포에서도 if문을 담을 수 있다.

result = [elem for elem in a if 조건]

이런 식이다. 즉, if조건이 맨 뒤로간다. 조심해야할 것은 if문을 통과한 elem만 리스트로 담겨진다는 것이다.

이를 이용하여 홀수만 있는 리스트를 만들어보자

result = [elem for elem in range(10) if elem % 2 == 1]
print(result) # [1, 3, 5, 7, 9]

조금 복잡하지만 for문을 2개 이상 사용하는 것도 가능하다. 물론 이 경우는 그냥 풀어쓰는게 가독성에 좋다.

result = [x*y for x in range(2, 10)
                for y in range(1,10)]

print(result)
# [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]

5. enumerate

enumerate()는 인자로 리스트나 문자열, 튜플과 같은 iterable을 받으면 해당 element가 반복 몇 번째에 해당하는 지 나타낸다.

t = [1, 5, 32, 14, -1, 23]
for value in enumerate(t):
    print(value)
#(0, 1)
#(1, 5)
#(2, 32)
#(3, 14)
#(4, -1)
#(5, 23)

다음과 같이 enumerateiterable이 오면 튜플을 만들고 튜플안에 몇 번째 반복에 해당하는 값인지 나타낸다.

튜플이기 때문에 다음과 같이 받을 수 있다.

t = [1, 5, 32, 14, -1, 23]
for i, v in enumerate(t):
    print(i , v)
#0 1
#1 5
#2 32
#3 14
#4 -1
#5 23

즉, 튜플 할당이 가능하다.

0개의 댓글