본문 바로가기
목차
Python

match statement-Structural Pattern Matching-match/case

by ds31x 2025. 8. 11.
728x90
반응형

Python match/case Tutorial — 구조적 패턴 매칭

1. match/case

  • match case는 Python 3.10에 도입된 구조적 패턴 매칭(Structural Pattern Matching) 기능임.
    • 단순 값 비교뿐 아니라, 자료구조의 모양(구조)을 분해하여 조건에 맞춰 분기할 수 있음.
    • C언어의 switch 문과 매우 유사한 형태이나 보다 강력한 기능을 가짐.
  • Python 3.10 (2021년 10월)부터 사용 가능
  • 도입배경:
    • if/elif로 길게 나열하던 분기문을 더 간결하고 읽기 쉽게 표현
    • JSON, 딕셔너리, 튜플, 리스트, 데이터클래스, Enum 등 구조화된 데이터의 패턴을 직관적으로 매칭

자료구조의 모양(구조) 즉, 데이터 모양으로 분기하는 경우
match/caseif/elif보다 가독성이 좋음

  • 기본 문법:
    match subject:
        case pattern1:
            # pattern1 매칭 시 실행
        case pattern2:
            # pattern2 매칭 시 실행
        case _:
            # default

 

참고로, matchcase는 soft keyword임.

https://dsaint31.tistory.com/510

 

[Python] Keyword란? (Soft Keyword 포함)

Keywords (or Reserved Words)Keyword란 Python에서 특별한 단어 (special word)들을 가르킨다.Keyword들은 Python에서 특정한 목적으로 사용되도록 이미 정해진 word들로Python에서 정해놓은 방법 외로는 사용을 할 수

dsaint31.tistory.com

 


2. Simple Example

def http_status(status):
    match status:
        case 200:                       # literal pattern
            return "OK"
        case 404 | 410:                 # OR Pattern (대안 패턴)
            return "Not Found"
        case x if 500 <= x < 600:       # Guard Pattern (가드 패턴)
            return "Server Error"
        case _:                         # Wildcard Pattern (와일드카드 패턴)
            return "Unknown"

print(http_status(200))
print(http_status(404))
print(http_status(503))
print(http_status(123))

출력

OK
Not Found
Server Error
Unknown

3. 패턴별 Example

3-1. Literal Pattern (리터럴 패턴) & Value Pattern (값 패턴)

  • Literal Pattern(리터럴 패턴) — 숫자·문자열·None 등 값 자체와 정확히 일치하는지 비교
  • Value Pattern(값 패턴) — Color.RED처럼 도트(.) 를 통한 속성의 값과 비교하는 패턴 (반드시 패턴에 .가 포함되어야 함)
    • 변수가 직접 case 뒤에 놓이면 Capture Pattern으로 동작함: 주의 (3-2 확인할 것)
    • 변수 값을 사용하는 case를 만들려면 Guard Pattern을 사용해야함.

Litteral Pattern의 예는 다음과 같음 (Simple Example과 거의 유사):

def http_status(status):
    match status:
        case 200:            # literal pattern
            return "OK"
        case 404:            # literal pattern     
            return "Not Found"
        case _:              # Wildcard Pattern (와일드카드 패턴)
            return "Unknown"

print(http_status(200))
print(http_status(404))
print(http_status(123))

 

Value Pattern 또는 Attribute Pattern이라고도 불리는 사용예:

from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

def color_name(c):
    match c:
        case Color.RED:      # Value Pattern: 도트 표기된 상수 값과 비교
            return "red"
        case Color.GREEN:    # Value Pattern
            return "green"
        case None:           # Literal Pattern: None과 정확히 일치
            return "unknown"
        case _:              # Wildcard Pattern: 기본값
            return "other"

print(color_name(Color.RED))
print(color_name(Color.BLUE))
print(color_name(None))
print(color_name(123))

출력

red
other
unknown
other

 

2024.03.24 - [Python] - [Python] Enum (열거형, Enumeration Type)

 

[Python] Enum (열거형, Enumeration Type)

Enum은 Enumeration type의 abbreviation. 한정된 수의 가능한 값을 value로 가질 수 있는 데이터 타입 을 가르킴.(보통 프로그래머가 가질 수 있는 값들의 집합을 정의해줌.) 프로그래밍에서 Enum을 사용하면

ds31x.tistory.com


3-2. Capture Pattern (캡처 패턴) & Wildcard Pattern (와일드카드 패턴)

  • Capture Pattern(캡처 패턴): 매칭된 값을 새로운 변수에 저장하여 이후 코드에서 사용할 수 있게 하는 패턴
    • case x: 처럼 사용.
    • Value Pattern에서 . 표기가 반드시 필요한 이유는, case NAME: 형태가 기본적으로 capture pattern으로 해석되기 때문임.
    • 매칭된 값을 새로운 변수로 binding한다고 Python에서는 언급!
  • Wildcard Pattern(와일드카드 패턴): _ 를 사용해 어떤 값이든 매칭하되 변수에 저장하지 않고 무시하는 패턴.
    • C 언어 switch statement 의 default와 같은 역할을 수행하는데 많이 사용됨.
    • 사실 capture pattern이고, 잘 안쓰이는 변수명에 capture한 것에 불과함.
def describe(value):
    match value:
        case x:          # Capture Pattern: 어떤 값이든 x에 저장
            return f"value is {x}"
        # case _:          # 이 예제에서는 실행되지 않음
        #     return "anything"

print(describe(42))
print(describe("hello"))

출력

value is 42
value is hello

 


3-3. OR Pattern (OR 패턴)

  • OR Pattern(OR 패턴):
    • A | B 처럼 여러 패턴 중 하나라도 매칭되면
    • 해당 분기를 실행하는 패턴.
    • OR 패턴은 양쪽이 동일한 variable binding set을 가져야 함
    • binding : identifier에 특정 attribute나 object를 연결하는 행위
def is_weekend(day):
    match day:
        case "Sat" | "Sun":
            return True
        case _:
            return False

print(is_weekend("Sat"))
print(is_weekend("Mon"))

출력

True
False

 

2024.06.06 - [Python] - [Programming] Binding: Name Binding and Language Binding

 

[Programming] Binding: Name Binding and Language Binding

Programming에서의 Binding(binding)이란?binding은 프로그램이 실행되는 동안 특정 identifier (or name)에어떤 속성이나 객체 등의 실제 대상을 binding(연결)하는 것을 의미함.Binding의 기본 개념Name or Identifier Us

ds31x.tistory.com

 

다음의 예는 동일한 변수 바인딩 집합이 아닌 경우로 에러 발생: SyntaxError: alternative patterns bind different names

# 서로 다른 이름(p, q)을 바인딩 → 오류
match req:
    case ("GET", p) | ("POST", q):
        ...

# 한쪽만 캡처, 다른 쪽은 바인딩 없음 → 오류
match req:
    case ("GET", p) | ("POST", _):
        ...

# 한쪽은 x를 바인딩, 다른 쪽은 바인딩 없음(리터럴만) → 오류
match v:
    case (x, 1) | (2, 3):
        ...

# 중첩 패턴이라도 결과적으로 바인딩 집합이 다르면 오류
match msg:
    case ("GET", {"id": id}) | ("POST", {}):
        ...

3-4. Guard Pattern (가드 패턴)

  • Guard Pattern(가드 패턴):
    • 패턴이 먼저 매칭된 뒤
    • if 조건을 추가로 검사하여
    • 최종 매칭 여부를 결정하는 패턴.
  • 변수의 값으로 판정하는 경우엔 이를 반드시 이용해야 한다.
    • 3.12 이후에 전역변수(주로 상수)를 대문자로 변수명을 삼은 경우는 앞에 dot(.)을 놓아서 case에서 활용가능.
    • 하지만 지역변수에선 동작안하므로 Gaurd Pattern으로 하는게 현재까지 최선임.
v = 0 # 변수의 값을 기반으로 match의 case에서 활용.
def classify(n):
    match n:
        case x if x < v:
            return "neg"
        case 0:
            return "zero"
        case x if x > v:
            return "pos"

print(classify(-3))
print(classify(0))
print(classify(7))

출력

neg
zero
pos

3-5. Sequence Pattern (시퀀스 패턴)

  • Sequence Pattern(시퀀스 패턴):
    • 리스트·튜플 등의 시퀀스 에 적용.
    • 시퀀스의 길이와 요소 구조를 비교하여 매칭하는 패턴.
    • 일종의 capture pattern 을 sequence 타입에 지정한 것.
def head_tail(seq):
    match seq:
        case []:
            return "empty"
        case [x]:
            return f"one: {x}"
        case [x, y]:
            return f"two: {x}, {y}"
        case [head, *tail]:
            return f"head={head}, tail={tail}"

print(head_tail([]))
print(head_tail([10]))
print(head_tail([1, 2]))
print(head_tail([1, 2, 3, 4]))

출력

empty
one: 10
two: 1, 2
head=1, tail=[2, 3, 4]

3-6. Mapping Pattern (매핑 패턴; 딕셔너리)

  • Mapping Pattern(매핑 패턴):
    • 딕셔너리에서 지정한 키가 존재하고
    • 해당 값이 패턴과 일치하는지 비교하여 매칭하는 패턴.
def handle(msg):
    match msg:
        case {"type": "error", "code": c, **rest}:
            return f"ERROR {c}, rest={rest}"
        case {"type": "event", "name": n}:
            return f"EVENT {n}"
        case _:
            return "unknown"

print(handle({"type": "error", "code": 404, "msg": "nope"}))
print(handle({"type": "event", "name": "login"}))
print(handle({"type": "other"}))

출력

ERROR 404, rest={'msg': 'nope'}
EVENT login
unknown

3-7. Class Pattern (클래스 패턴; dataclass / NamedTuple 포함)

  • Class Pattern(클래스 패턴):
    • dataclassNamedTuple
    • 객체의 타입과 필드 값을 지정된 패턴과 비교하여 매칭하는 패턴.
from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

def where(p):
    match p:
        case Point(0, 0):
            return "origin"
        case Point(x=0, y=y):
            return f"on Y-axis: y={y}"
        case Point(x, y):
            return f"({x}, {y})"

print(where(Point(0, 0)))
print(where(Point(0, 5)))
print(where(Point(3, 4)))

출력

origin
on Y-axis: y=5
(3, 4)

3-8. As Pattern (as 패턴)

  • As Pattern(as 패턴):
    • 부분 패턴이 매칭되었을 때
    • 해당 부분과 전체 값을 동시에 변수에 바인딩하는 패턴.
def parse_pair(obj):
    match obj:
        case [x, y] as pair:
            return f"x={x}, y={y}, pair={pair}"
        case _:
            return "not a pair"

print(parse_pair([10, 20]))
print(parse_pair([10, 20, 30]))

출력

x=10, y=20, pair=[10, 20]
not a pair

3-9. Nested Pattern (중첩 패턴)

  • Nested Pattern(중첩 패턴):
    • 패턴 안에 또 다른 패턴을 포함시켜
    • 계층적·구조적으로 매칭하는 패턴.
def nested(d):
    match d:
        case {"pt": (0, y)}:
            return f"on Y-axis at y={y}"
        case {"pt": (x, y)}:
            return f"point=({x},{y})"
        case _:
            return "no point"

print(nested({"pt": (0, 7)}))
print(nested({"pt": (3, 4)}))
print(nested({"no": "point"}))

출력

on Y-axis at y=7
point=(3,4)
no point

같이 보면 좋은 자료들

https://gist.github.com/dsaint31x/ccb40128898f2099ffdc6878427b2cce

 

py_match_statement_310.ipynb

py_match_statement_310.ipynb. GitHub Gist: instantly share code, notes, and snippets.

gist.github.com


2023.10.06 - [Pages] - [Python] Control Structure and Control Flow

 

[Python] Control Structure and Control Flow

Control structure와 Control Flow란 무엇인가?2025.04.23 - [Python] - [Programming] Control Flow 와 Control Structure [Programming] Control Flow 와 Control StructureAbstraction(추상화)을 통한 이해프로그래밍 언어에서 Abstraction은

ds31x.tistory.com


728x90

'Python' 카테고리의 다른 글

Exceptions and Debugging Tools  (1) 2025.08.18
CLI Program에서의 arguments - argparse모듈  (1) 2025.08.12
rounding 종류: C, Java, Python - Banker's Rounding  (4) 2025.08.09
docstring  (3) 2025.08.07
webbrowser 모듈 사용법  (2) 2025.08.07