- Level: Beginner
- Prerequisites: Programming/Variables-and-Types.md
- Status: Draft
- Reviewed-by: -
- Depth: Deep-dive (자기완결)
제어 흐름은 프로그램의 실행 순서를 정하는 방법이다. 조건문은 어떤 조건이 참일 때만 특정 코드를 실행하고, 반복문은 같은 작업을 여러 번 실행한다.
프로그램이 항상 위에서 아래로 한 번만 실행된다면 할 수 있는 일이 매우 제한된다. 조건문은 갈림길이고, 반복문은 되풀이 작업을 자동화하는 장치다.
- 조건문: "비밀번호가 맞으면 로그인한다."
- 반복문: "목록에 있는 모든 점수를 더한다."
- 조기 종료: "원하는 값을 찾으면 더 찾지 않는다."
flowchart TD
START["시작"] --> CHECK{"조건?"}
CHECK -- 참 --> THEN["then 분기"]
CHECK -- 거짓 --> ELSE["else 분기"]
THEN --> LOOP{"반복 조건?"}
ELSE --> LOOP
LOOP -- 참 --> BODY["본문 실행 + 상태 갱신"]
BODY --> LOOP
LOOP -- 거짓 --> END["종료"]
조건문은 불리언 표현식을 기준으로 분기한다.
if 조건:
조건이 참일 때 실행
else:
조건이 거짓일 때 실행
반복문은 보통 두 종류로 나뉜다.
| 종류 | 쓰임 |
|---|---|
| for 반복문 | 정해진 범위나 컬렉션을 순회 |
| while 반복문 | 조건이 참인 동안 계속 반복 |
반복문에는 종료 조건이 있어야 한다. 종료 조건이 없거나 갱신이 잘못되면 무한 루프가 된다.
반복문을 깊게 이해하려면 두 질문을 한다.
- 반복 불변식(loop invariant): 매 반복 시작 시 항상 참이어야 하는 사실은 무엇인가.
- 종료 측도(variant): 반복이 진행될수록 줄어들어 결국 종료를 보장하는 값은 무엇인가.
예를 들어 최댓값 찾기에서 best는 "지금까지 본 값 중 최댓값"이라는 불변식을 갖는다. 인덱스 i는 매번 증가하고 배열 길이에 도달하면 종료한다.
조건문 예시:
score = 82
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
else:
grade = "C or below"
print(grade)반복문 예시:
scores = [90, 85, 100]
total = 0
for score in scores:
total += score
average = total / len(scores)
print(average)while은 반복 횟수가 미리 정해지지 않았을 때 유용하다.
n = 16
steps = 0
while n > 1:
n //= 2
steps += 1
print(steps)워크드 예제:
values = [3, 1, 9, 2]
best = values[0]
for i in range(1, len(values)):
if values[i] > best:
best = values[i]
print(best) # 9반복 시작 시점마다 best는 values[0:i]의 최댓값이다. i=1이면 [3]의 최댓값 3, i=3이면 [3,1,9]의 최댓값 9다. 이 불변식이 끝까지 유지되므로 반복 종료 뒤 best는 전체 배열의 최댓값이다.
| 구조 | 시간 | 공간 |
|---|---|---|
| 단일 조건문 | O(1) | O(1) |
| 길이 n 목록 한 번 순회 | O(n) | O(1) |
| 이중 반복문으로 n x n 순회 | O(n^2) | O(1) |
반복문 개수만 세는 것보다 각 반복문이 몇 번 실행되는지를 계산하는 것이 중요하다.
예를 들어 while n > 1: n //= 2는 반복마다 n이 절반으로 줄어 O(log n)이다. 반면 while n > 1: n -= 1은 O(n)이다. 코드 모양보다 상태가 어떻게 변하는지가 복잡도를 결정한다.
- 입력값 검증
- 목록 검색과 필터링
- 누적합, 최댓값, 최솟값 계산
- 시뮬레이션과 게임 루프
- 알고리즘의 기본 골격 구성
if가 여러 개 있는 것과if / elif / else는 다르다. 전자는 조건을 각각 검사하고, 후자는 한 분기만 선택한다.- 반복문 안에서 제어 변수를 갱신하지 않으면 무한 루프가 될 수 있다.
break는 반복문 전체를 끝내고,continue는 현재 반복만 건너뛴다.- 중첩 반복문이 항상 O(n^2)은 아니다. 각 루프의 반복 횟수를 따로 봐야 한다.
- 구조적 프로그래밍이 널리 퍼지기 전에는
goto로 실행 위치를 직접 옮기는 코드가 흔했다. Dijkstra의 "Go To Statement Considered Harmful"은 조건문, 반복문, 함수 중심으로 코드를 구조화하는 흐름에 큰 영향을 주었다. - Python의
for는 C/Java의 전통적인 카운터 반복문보다 "반복 가능한 값들을 하나씩 꺼낸다"는 의미에 더 가깝다. - Python에는
for ... else문법이 있다. 반복문이break없이 끝났을 때else가 실행되는데, 처음 보면 조건문의else처럼 보여 헷갈리기 쉽다. - C와 Java에는
do ... while처럼 본문을 최소 한 번 실행하는 반복문이 있지만, Python에는 같은 모양의 전용 문법이 없다.
- 1부터 100까지의 정수 중 짝수만 출력하라.
- 주어진 점수 목록에서 최댓값과 평균을 구하라.
- 숫자 목록에서 처음으로 음수가 나오는 위치를 찾고, 없으면
-1을 출력하라.