python control flow, python if, python for, python while, match statement, structural pattern matching
if / elif / else
x = 10if 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의 for는 iterable 순회 전용. 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)
결과
012abca 1b 21 alice2 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: 30bob: 25carol: 35
for-else
루프가 break 없이 끝나면else 블록이 실행된다. 검색 패턴에 유용.
python
target = 99for x in [1, 2, 3]: if x == target: print("found") breakelse: print("not found") # break 없이 끝나면 실행
결과
not found
while-else도 동일.
while 루프
n = 10while n > 0: print(n) n -= 1else: print("done") # 조건이 거짓이 되어 끝나면 실행# 무한 루프 + breakwhile 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(): passif 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@dataclassclass Point: x: int y: intp = 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): passelse: # 예외 없이 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은 캐시 친화적 아님 → 리스트로 정렬 후 순회가 더 빠를 수 있음
💬 댓글