{"id":120041,"date":"2026-07-08T18:30:19","date_gmt":"2026-07-08T13:00:19","guid":{"rendered":"https:\/\/www.guvi.in\/blog\/?p=120041"},"modified":"2026-07-08T18:30:22","modified_gmt":"2026-07-08T13:00:22","slug":"python-match-case","status":"publish","type":"post","link":"https:\/\/www.guvi.in\/blog\/python-match-case\/","title":{"rendered":"Python Match\/Case: Structural Pattern Matching Guide"},"content":{"rendered":"\n<p>Before Python 3.10, complex branching often required nested if-elif-else statements with multiple isinstance() checks and dictionary lookups. Python 3.10 introduced structural pattern matching (match\/case) through PEP 634, allowing code to python match and unpack data structures, dictionaries, and objects in a clean, readable way. It makes complex decision-making logic easier to write and maintain.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>TL;DR Summary<\/strong><\/h2>\n\n\n\n<ul>\n<li>Python 3.10 introduced structural pattern matching (match\/case) through PEP 634, enabling developers to match and unpack sequences, dictionaries, and objects in a single, readable statement. <\/li>\n\n\n\n<li>More powerful than a traditional switch statement, it reduces complex if-elif chains and isinstance() checks, making code cleaner and easier to maintain.<\/li>\n<\/ul>\n\n\n\n<p>Want to master modern Python from structural pattern matching and type hints through data science, automation, and backend development with structured projects and interview preparation? Check out<a href=\"https:\/\/www.guvi.in\/courses\/python-programming\/?utm_source=blog&amp;utm_medium=content&amp;utm_campaign=python-structural-pattern-matching\"> <\/a><strong>HCL GUVI&#8217;s <\/strong><a href=\"https:\/\/www.guvi.in\/courses\/programming\/python-zero-to-hero\/?utm_source=blog&amp;utm_medium=hyperlink&amp;utm_campaign=Python+match%2Fcase%3A+Structural+Pattern+Matching+Guide\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Python Programming Course<\/strong><\/a> designed for developers who want to go from Python basics to production-ready code.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Basic Syntax and How match\/case Works<\/strong><\/h2>\n\n\n\n<p>The structure of a match statement is straightforward. The subject, the value being inspected, is written after the match keyword. Each case block defines a pattern; Python tests them top to bottom and runs the first one that matches. The underscore wildcard (_) acts as a catch-all default.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def http_status(status):\n\nmatch status:\n\n&nbsp;&nbsp;&nbsp;&nbsp; case 200:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 'OK'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case 400:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 'Bad Request'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case 404:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 'Not Found'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case 500:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 'Internal Server Error'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case _:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 'Unknown status'\n\nprint(http_status(404)) &nbsp; # Not Found\n\nprint(http_status(301)) &nbsp; # Unknown status<\/code><\/pre>\n\n\n\n<p>Unlike a C-style switch, there is no fall-through between cases. The first matching case executes and the match block exits. The wildcard _ is not a variable&nbsp; it matches anything without binding the value.<\/p>\n\n\n\n<p><strong>Read More:<\/strong><a href=\"https:\/\/www.guvi.in\/blog\/list-comprehension-in-python\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong> <\/strong>Python List Comprehensions and Generator Expressions Explained<\/a><\/p>\n\n\n\n<p>Want to master modern Python from structural pattern matching and type hints through data science, automation, and backend development with structured projects and interview preparation? Check out<a href=\"https:\/\/www.guvi.in\/courses\/python-programming\/?utm_source=blog&amp;utm_medium=content&amp;utm_campaign=python-structural-pattern-matching\" target=\"_blank\" rel=\"noreferrer noopener\"> <strong>HCL GUVI&#8217;s Python Programming Course<\/strong><\/a> designed for developers who want to go from Python basics to production-ready code.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Pattern Types with Examples<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Sequence Patterns Matching Lists and Tuples<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>def describe_point(point):\n\nmatch point:\n\n&nbsp;&nbsp;&nbsp;&nbsp; case &#91;0, 0]:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 'Origin'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case &#91;x, 0]:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f'On x-axis at {x}'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case &#91;0, y]:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f'On y-axis at {y}'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case &#91;x, y]:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f'Point at ({x}, {y})'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case _:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 'Not a 2D point'\n\nprint(describe_point(&#91;3, 0])) &nbsp; # On x-axis at 3\n\nprint(describe_point(&#91;2, 5])) &nbsp; # Point at (2, 5)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Mapping Patterns Matching Dictionaries<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>def handle_event(event):\n\nmatch event:\n\n&nbsp;&nbsp;&nbsp;&nbsp; case {'type': 'click', 'button': btn}:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f'Mouse click: button {btn}'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case {'type': 'keypress', 'key': k}:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f'Key pressed: {k}'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case {'type': t}:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f'Unknown event type: {t}'\n\nprint(handle_event({'type': 'click', 'button': 'left'}))\n\n# Mouse click: button left<\/code><\/pre>\n\n\n\n<p>Mapping patterns do partial matching a dictionary with extra keys still matches as long as all the keys listed in the pattern are present. This makes them ideal for handling JSON payloads and API responses where additional fields may exist.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Class Patterns Matching Object Instances<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>from dataclasses import dataclass\n\n@dataclass\n\nclass Point:\n\nx: float\n\ny: float\n\n@dataclass\n\nclass Circle:\n\ncentre: Point\n\nradius: float\n\ndef describe_shape(shape):\n\nmatch shape:\n\n&nbsp;&nbsp;&nbsp;&nbsp; case Circle(centre=Point(x=0, y=0), radius=r):\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f'Circle at origin, radius {r}'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case Circle(centre=Point(x=cx, y=cy), radius=r):\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f'Circle at ({cx},{cy}), radius {r}'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case Point(x=0, y=0):\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 'Origin point'\n\nprint(describe_shape(Circle(Point(0, 0), 5)))\n\n# Circle at origin, radius 5<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>OR Patterns and Guards<\/strong><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>def classify(value):\n\nmatch value:\n\n&nbsp;&nbsp;&nbsp;&nbsp; case 'yes' | 'y' | 'true':\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 'Affirmative'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case 'no' | 'n' | 'false':\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 'Negative'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case int(n) if n &gt; 0:&nbsp; &nbsp; &nbsp; # guard condition\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f'Positive integer: {n}'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case int(n) if n &lt; 0:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return f'Negative integer: {n}'\n\n&nbsp;&nbsp;&nbsp;&nbsp; case _:\n\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 'Unrecognised'\n\nprint(classify('yes')) # Affirmative\n\nprint(classify(42)) &nbsp; # Positive integer: 42&nbsp;<\/code><\/pre>\n\n\n\n<div style=\"background-color: #099f4e; border: 3px solid #110053; border-radius: 12px; padding: 18px 22px; color: #FFFFFF; font-size: 18px; font-family: Montserrat, Helvetica, sans-serif; line-height: 1.6; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); max-width: 750px;\">\n\n  <strong style=\"font-size: 22px; color: #FFFFFF;\">\ud83d\udca1 Did You Know?<\/strong>\n  <br \/><br \/>\n\n  Python&#8217;s <strong style=\"color: #FFFFFF;\">structural pattern matching<\/strong>, introduced in <strong style=\"color: #FFFFFF;\">Python 3.10<\/strong>, was inspired by pattern matching features found in languages such as <strong style=\"color: #FFFFFF;\">Scala<\/strong>, <strong style=\"color: #FFFFFF;\">Haskell<\/strong>, <strong style=\"color: #FFFFFF;\">Erlang<\/strong>, and <strong style=\"color: #FFFFFF;\">Rust<\/strong>. The feature is specified across three companion Python Enhancement Proposals: <strong style=\"color: #FFFFFF;\">PEP 634<\/strong> (Specification), <strong style=\"color: #FFFFFF;\">PEP 635<\/strong> (Motivation and Rationale), and <strong style=\"color: #FFFFFF;\">PEP 636<\/strong> (Tutorial). Together, they provide one of the most comprehensive documentations ever published for a major Python language feature.\n\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Python Pattern Types: Quick Reference<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Pattern Type<\/strong><\/td><td><strong>Syntax Example<\/strong><\/td><td><strong>What It Matches<\/strong><\/td><\/tr><tr><td><strong>Literal<\/strong><\/td><td>case 42:<\/td><td>Exact value \u2014 integer, string, bool, None<\/td><\/tr><tr><td><strong>Capture<\/strong><\/td><td>case x:<\/td><td>Any value; binds it to variable x<\/td><\/tr><tr><td><strong>Wildcard<\/strong><\/td><td>case _:<\/td><td>Any value; discards it (default\/else)<\/td><\/tr><tr><td><strong>Sequence<\/strong><\/td><td>case [x, y]:<\/td><td>A list or tuple with exactly two elements<\/td><\/tr><tr><td><strong>Mapping<\/strong><\/td><td>case {&#8216;key&#8217;: v}:<\/td><td>A dict containing the given key; binds value to v<\/td><\/tr><tr><td><strong>Class<\/strong><\/td><td>case Point(x=a, y=b):<\/td><td>An instance of Point; binds attributes to a, b<\/td><\/tr><tr><td><strong>OR pattern<\/strong><\/td><td>case &#8216;yes&#8217; | &#8216;y&#8217;:<\/td><td>Any of the listed literals<\/td><\/tr><tr><td><strong>Guard<\/strong><\/td><td>case n if n &gt; 0:<\/td><td>Matches n and only if the guard condition is true<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Real-World Use Cases<\/strong><\/h2>\n\n\n\n<p>Structural pattern matching is not just a cleaner switch&nbsp; it shines in scenarios where the shape and content of data varies unpredictably.<\/p>\n\n\n\n<ul>\n<li><strong>API and JSON response handling:<\/strong> Match on response dictionaries by key presence to route success, error, and pagination responses without nested isinstance and .get() chains.<\/li>\n\n\n\n<li><strong>Command-line parsers:<\/strong> Match tokenised command strings like [&#8216;move&#8217;, &#8216;up&#8217;, &#8216;5&#8217;] or [&#8216;quit&#8217;] to dispatch actions cleanly without lengthy elif blocks.<\/li>\n\n\n\n<li><strong>State machines:<\/strong> Match a (state, event) tuple to transition logic \u2014 the combination of sequence patterns and guards makes state transition tables readable and compact.<\/li>\n\n\n\n<li><strong>AST and compiler tools:<\/strong> Match node types in abstract syntax trees when writing linters, transpilers, or code analysis tools that inspect Python or custom language ASTs.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Common Mistakes with match\/case<\/strong><\/h2>\n\n\n\n<p><strong>1. Treating capture patterns like equality checks: <\/strong>case x: does not check whether the subject equals a variable named x it always matches and binds the subject to x. To compare against an existing variable, use a dotted name (case Status. OK:) or a guard (case n if n == threshold:).<\/p>\n\n\n\n<p><strong>2. Expecting fall-through behaviour: <\/strong>Python match has no fall-through. Each case is independent. If you need to share logic between cases, extract it into a function and call it from multiple case blocks do not rely on sequential execution.<\/p>\n\n\n\n<p><strong>3. Using match\/case below Python 3.10: <\/strong>The match and case keywords are syntax errors in Python 3.9 and below. Check your interpreter version with python &#8211;version before deploying code that uses structural pattern matching, especially in shared or containerised environments.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>Structural pattern matching is one of the most expressive additions to Python in years. It replaces brittle chains of isinstance checks and nested conditionals with a declarative syntax that simultaneously tests the shape of data, extracts its components, and routes execution all in one readable block. Literal patterns handle simple value dispatch. Sequence patterns destructure lists and tuples. Mapping patterns extract dictionary values without .get() boilerplate. Class patterns match object instances by attribute. OR patterns and guards add precision without nesting.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>FAQs<\/strong><\/h2>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list \">\n<div id=\"faq-question-1783489725042\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">\u00a01. <strong>What is structural pattern matching in Python?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Structural pattern matching, introduced in Python 3.10 via PEP 634, is a control-flow feature that lets you match a value against a series of patterns using match and case keywords. Unlike a simple switch statement,<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1783489730122\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">2. <strong>Is Python match\/case the same as a switch statement?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>No. A switch statement in languages like Java or C tests a single value for equality against a list of constants. Python&#8217;s match tests a subject against structural patterns it can inspect the shape of a list, the keys present in a dictionary, the type and attributes of an object, and apply conditional guards. It is far more powerful than a traditional switch.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1783489739220\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">3. <strong>What Python version is required for match\/case?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Python 3.10 or higher is required. The match and case keywords are valid syntax only from 3.10 onwards they are syntax errors in 3.9 and earlier. You can check your version with python &#8211;version in the terminal. Python 3.10 was released in October 2021.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1783489747551\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">4.<strong>What is a wildcard pattern in Python match?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>The wildcard pattern is written as a single underscore (_). It matches any value without binding it to a variable. Placed as the last case in a match block, it acts as the default catch-all equivalent to the else clause in an if-elif-else chain. Unlike a capture pattern (case x:), the value is discarded.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1783489762154\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">5. <strong>What is the difference between a capture pattern and a literal pattern?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>A literal pattern (case 42: or case &#8216;error&#8217;:) tests the subject for equality against a specific value. A capture pattern (case x:) always matches and binds the subject value to the variable name it never tests equality. This is a common source of bugs: case existing_var: does not compare against existing_var; it shadows it with a new binding.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1783489769725\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">6. <strong>How do guard conditions work in Python match?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>A guard is an if clause appended to a case pattern: case n if n > 0:. The pattern must match first; then the guard condition is evaluated. If the guard is False, Python moves to the next case even though the pattern itself matched. Guards are essential for adding numeric range checks or attribute comparisons that patterns alone cannot express.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1783489778090\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \">7. <strong>Can I use match\/case with custom classes?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Yes. Class patterns match instances of a specific class and extract named attributes. For dataclasses and named tuples, this works automatically. For plain classes, you define a __match_args__ class variable a tuple of attribute names to enable positional pattern matching. Named attribute matching (case Point(x=a, y=b):) works without __match_args__.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>Before Python 3.10, complex branching often required nested if-elif-else statements with multiple isinstance() checks and dictionary lookups. Python 3.10 introduced structural pattern matching (match\/case) through PEP 634, allowing code to python match and unpack data structures, dictionaries, and objects in a clean, readable way. It makes complex decision-making logic easier to write and maintain.&nbsp; TL;DR [&hellip;]<\/p>\n","protected":false},"author":63,"featured_media":122003,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[717],"tags":[],"views":"56","authorinfo":{"name":"Vishalini Devarajan","url":"https:\/\/www.guvi.in\/blog\/author\/vishalini\/"},"thumbnailURL":"https:\/\/www.guvi.in\/blog\/wp-content\/uploads\/2026\/07\/python-match-case-300x120.webp","_links":{"self":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/120041"}],"collection":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/users\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/comments?post=120041"}],"version-history":[{"count":5,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/120041\/revisions"}],"predecessor-version":[{"id":122005,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/120041\/revisions\/122005"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/media\/122003"}],"wp:attachment":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/media?parent=120041"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/categories?post=120041"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/tags?post=120041"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}