본문으로 건너뛰기
김신건의 로그

[Python] 제어 흐름: if, for, while, match

· 수정 · 📖 약 1분 · 387자/단어 #python #control-flow #if #for #while #match #basics
python control flow, python if, python for, python while, match statement, structural pattern matching

if / elif / else

x = 10

if x > 0:
    sign = "positive"
elif x < 0:
    sign = "negative"
else:
    sign = "zero"

# 삼항 표현식
sign = "positive" if x > 0 else ("negative" if x < 0 else "zero")

Python에는 switch가 없었으나 3.10+ match 문이 추가됐다(아래 참고).

for 루프

Python의 foriterable 순회 전용. C의 인덱스 카운팅 for는 없음. range() 사용.

python
for i in range(3):
  print(i)

for ch in "abc":
  print(ch)

for k, v in {"a": 1, "b": 2}.items():
  print(k, v)

# enumerate: 인덱스 동반
for i, name in enumerate(["alice", "bob"], start=1):
  print(i, name)
결과
0
1
2
a
b
c
a 1
b 2
1 alice
2 bob

zip: 여러 iterable 동시 순회

python
names = ["alice", "bob", "carol"]
ages = [30, 25, 35]

for n, a in zip(names, ages):
  print(f"{n}: {a}")

# 3.10+ strict=True: 길이 다르면 ValueError
# for n, a in zip(names, ages, strict=True): ...

# 길이 다를 때 짧은 쪽 기준
list(zip([1, 2, 3], [10, 20]))      # [(1, 10), (2, 20)]
결과
alice: 30
bob: 25
carol: 35

for-else

루프가 break 없이 끝나면 else 블록이 실행된다. 검색 패턴에 유용.

python
target = 99
for x in [1, 2, 3]:
  if x == target:
      print("found")
      break
else:
  print("not found")    # break 없이 끝나면 실행
결과
not found

while-else도 동일.

while 루프

n = 10
while n > 0:
    print(n)
    n -= 1
else:
    print("done")    # 조건이 거짓이 되어 끝나면 실행

# 무한 루프 + break
while True:
    cmd = input("> ")
    if cmd == "quit":
        break
    handle(cmd)

워러스 연산자(:=)와 결합하면 깔끔.

while line := input("> "):
    process(line)

break, continue, pass

for x in data:
    if x is None:
        continue          # 다음 반복으로
    if x.is_error:
        break             # 루프 탈출
    process(x)

# pass: 아무것도 안 함 (자리채움)
def todo():
    pass

if some_cond:
    pass    # 나중에 구현

pass는 빈 블록 자리 채움용. ...(Ellipsis)도 같은 목적으로 자주 쓰임 (특히 typing stub).

match 문 (3.10+, PEP 634)

구조적 패턴 매칭. C의 switch보다 강력하다.

python
def describe(p):
  match p:
      case (0, 0):
          return "원점"
      case (x, 0):
          return f"x축 위 (x={x})"
      case (0, y):
          return f"y축 위 (y={y})"
      case (x, y) if x == y:
          return f"y=x 대각선 (x={x})"
      case (x, y):
          return f"일반 점 ({x}, {y})"
      case _:
          return "튜플 아님"

for p in [(0, 0), (5, 0), (3, 3), (1, 2)]:
  print(describe(p))
결과
원점
x축 위 (x=5)
y=x 대각선 (x=3)
일반 점 (1, 2)

패턴 종류

  • 리터럴: case 0:, case "ok":
  • 시퀀스: case [a, b, *rest]:
  • 매핑: case {"type": "user", "name": name}:
  • 클래스: case Point(x=0, y=y):
  • OR: case 401 | 403 | 404:
  • 가드: case x if x > 0:
  • as 바인딩: case [x, y] as point:
  • 와일드카드: case _:
def handle(event):
    match event:
        case {"type": "click", "x": x, "y": y}:
            click_at(x, y)
        case {"type": "key", "code": code} if code in (27, 13):
            handle_special(code)
        case {"type": "key", "code": _}:
            pass
        case _:
            unknown(event)

클래스 매칭과 match_args

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

p = Point(3, 4)
match p:
    case Point(x=0, y=0): print("원점")
    case Point(x=0, y=y): print(f"y축 ({y})")
    case Point(x=x, y=y): print(f"({x}, {y})")

# dataclass는 __match_args__를 자동 생성
# 위치 매칭도 가능: case Point(0, 0)

try/except/else/finally

예외 처리도 제어 흐름. 자세한 건 별도 페이지(py-exceptions 예정).

try:
    result = do_work()
except ValueError as e:
    handle(e)
except (KeyError, IndexError):
    pass
else:
    # 예외 없이 try 끝나면
    finalize(result)
finally:
    # 항상 실행
    cleanup()

with: 컨텍스트 관리자

자원 획득/해제를 안전하게.

with open("file.txt") as f:
    data = f.read()
# f 자동 close

# 여러 자원
with open("in.txt") as r, open("out.txt", "w") as w:
    w.write(r.read())

with 블록을 빠져나가면 예외 여부와 무관하게 __exit__() 호출 보장.

성능 노트

  • 컴프리헨션 > for+append (전용 바이트코드 빠름)
  • for x in some_set: O(n)이지만 set은 캐시 친화적 아님 → 리스트로 정렬 후 순회가 더 빠를 수 있음
  • while True + breakfor-else보다 의도가 명확할 때가 많음
  • match 문은 if/elif 사슬보다 약간 빠르고 가독성 향상

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기