๐ Match-Case Statements
The match-case statement is used to compare a value against different patterns.
It is similar to switch-case in some other programming languages.
Basic Syntax
match value:
case pattern1:
# code
case pattern2:
# code
case _:
# default code๐ข Basic Example
day = 2
match day:
case 1:
print("Monday")
case 2:
print("Tuesday") #This match will be executed
case 3:
print("Wednesday")
case _:
print("Invalid day")Python checks each case until it finds a match.
๐น Default Case _
The _ acts as the default case.
choice = 5
match choice:
case 1:
print("Start")
case 2:
print("Exit")
case _:
print("Invalid choice") #This match will be executed๐น Multiple Values in One Case
You can match multiple values using |.
day = "Saturday"
match day:
case "Saturday" | "Sunday":
print("Weekend") #This block will be executed
case _:
print("Weekday")๐น match-case vs if-elif-else
The same logic can be written using if-elif:
day = 2
if day == 1:
print("Monday")
elif day == 2:
print("Tuesday")
else:
print("Invalid")Using match-case:
match day:
case 1:
print("Monday")
case 2:
print("Tuesday")
case _:
print("Invalid")Note: match-case was introduced in Python 3.10 and is especially useful when you have many possible patterns to match.
<div class="infographic-pymatch">
<style>
.infographic-pymatch {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--ok: #1a7f4e;
--ok-soft: #e3f5ec;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', -apple-system, sans-serif;
--mono-font: 'IBM Plex Mono', 'Courier New', monospace;
max-width: 680px;
margin: 0 auto;
box-sizing: border-box;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-pymatch[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--ok: #5cd6a0;
--ok-soft: #16342a;
}
.infographic-pymatch * { box-sizing: border-box; }
.infographic-pymatch .ig-inner { padding: 1.75rem clamp(1.25rem, 5vw, 3rem) 2rem; }
.infographic-pymatch .ig-title {
font-family: var(--display-font); font-size: clamp(1.4rem, 4.5vw, 1.9rem);
font-weight: 600; text-align: center; margin: 0 0 0.4rem;
}
.infographic-pymatch .ig-subnote {
text-align: center; font-size: 0.76rem; color: var(--ink-soft); margin: 0 0 1.5rem;
}
.infographic-pymatch .controls { display: flex; flex-direction: column; align-items: center; gap: 0.6rem; }
.infographic-pymatch .input-wrap { position: relative; }
.infographic-pymatch .input-tag {
position: absolute; top: -1.35rem; left: 50%; transform: translateX(-50%);
font-size: 0.65rem; font-family: var(--mono-font); color: var(--accent);
background: var(--accent-soft); padding: 0.1rem 0.45rem; border-radius: 4px; white-space: nowrap;
}
.infographic-pymatch .fruit-input {
width: 9rem; height: 2.6rem; font-family: var(--mono-font); font-size: 1rem; font-weight: 700;
text-align: center; padding: 0 0.4rem; border: 1px solid var(--line); background: var(--paper-alt);
color: var(--ink); outline: none;
}
.infographic-pymatch .fruit-input:focus { border-color: var(--accent); }
.infographic-pymatch .presets { display: flex; gap: 0.4rem; justify-content: center; margin-top: 1.6rem; width: 100%; flex-wrap: wrap; }
.infographic-pymatch .preset-btn {
font: inherit; font-size: 0.75rem; font-family: var(--mono-font); border: 1px dashed var(--line);
background: var(--paper); color: var(--ink-soft); padding: 0.3rem 0.65rem; border-radius: 4px; cursor: pointer;
}
.infographic-pymatch .preset-btn:hover { border-color: var(--accent); color: var(--accent); }
.infographic-pymatch .stage { margin-top: 1.5rem; display: flex; justify-content: center; }
.infographic-pymatch .stage svg { width: 100%; max-width: 560px; height: auto; overflow: visible; }
.infographic-pymatch .fc-shape { fill: var(--paper-alt); stroke: var(--line); stroke-width: 1.8; transition: fill 0.2s, stroke 0.2s; }
.infographic-pymatch .fc-block.reached { fill: var(--ok-soft); stroke: var(--ok); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pymatch .fc-pill { fill: var(--accent-soft); stroke: var(--accent); }
.infographic-pymatch .fc-switch { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 2; }
.infographic-pymatch .fc-text { font-family: var(--mono-font); font-size: 12px; fill: var(--ink); text-anchor: middle; }
.infographic-pymatch .fc-text.on-pill { fill: var(--accent); font-weight: 700; }
.infographic-pymatch .fc-text.on-switch { fill: var(--accent); font-weight: 700; }
.infographic-pymatch .fc-text.on-block { font-weight: 700; }
.infographic-pymatch .case-tag {
font-family: var(--mono-font); font-size: 9.5px; fill: var(--ink-soft); text-anchor: middle;
}
.infographic-pymatch .fc-edge path { stroke: var(--line); stroke-width: 2; fill: none; transition: stroke 0.2s; }
.infographic-pymatch .fc-edge polygon { fill: var(--line); transition: fill 0.2s; }
.infographic-pymatch .fc-edge.is-check path { stroke: var(--accent); stroke-width: 2.5; }
.infographic-pymatch .fc-edge.is-check polygon { fill: var(--accent); }
.infographic-pymatch .fc-edge.is-taken path { stroke: var(--ok); stroke-width: 2.5; }
.infographic-pymatch .fc-edge.is-taken polygon { fill: var(--ok); }
.infographic-pymatch .junction { fill: var(--line); transition: fill 0.2s; }
.infographic-pymatch .junction.is-taken { fill: var(--ok); }
.infographic-pymatch .caption {
text-align: center; font-size: 0.9rem; color: var(--ink-soft); margin-top: 1.25rem;
}
.infographic-pymatch .caption strong { color: var(--ink); font-family: var(--mono-font); }
@media (prefers-reduced-motion: reduce) {
.infographic-pymatch *, .infographic-pymatch *::before, .infographic-pymatch *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="ig-inner">
<h2 class="ig-title">The match Statement</h2>
<p class="ig-subnote">Python 3.10+ โ structural pattern matching</p>
<div class="controls">
<div class="input-wrap">
<span class="input-tag">fruit</span>
<input type="text" class="fruit-input" id="fruitInput" value="apple" autocomplete="off" spellcheck="false">
</div>
<div class="presets">
<button class="preset-btn" data-v="apple">apple</button>
<button class="preset-btn" data-v="banana">banana</button>
<button class="preset-btn" data-v="orange">orange</button>
<button class="preset-btn" data-v="kiwi">kiwi</button>
</div>
</div>
<div class="stage">
<svg viewBox="0 0 620 500" xmlns="http://www.w3.org/2000/svg">
<!-- Start -->
<g id="n-start">
<rect class="fc-shape fc-pill" x="240" y="10" width="140" height="42" rx="21"></rect>
<text class="fc-text on-pill" x="310" y="36">Start</text>
</g>
<!-- Start -> Match -->
<g class="fc-edge" id="e-start-sw">
<path d="M310,52 L310,89"></path>
<polygon points="310,95 305,85 315,85"></polygon>
</g>
<!-- Match node -->
<g id="n-switch">
<rect class="fc-switch" x="230" y="95" width="160" height="50" rx="6"></rect>
<line x1="238" y1="95" x2="238" y2="145" stroke="var(--accent)" stroke-width="2"></line>
<line x1="382" y1="95" x2="382" y2="145" stroke="var(--accent)" stroke-width="2"></line>
<text class="fc-text on-switch" x="310" y="124">match fruit:</text>
</g>
<!-- Fan-out lines from match to each case block -->
<g class="fc-edge" id="e-sw-b1"><path d="M270,145 L85,225"></path></g>
<g class="fc-edge" id="e-sw-b2"><path d="M300,145 L235,225"></path></g>
<g class="fc-edge" id="e-sw-b3"><path d="M320,145 L385,225"></path></g>
<g class="fc-edge" id="e-sw-b4"><path d="M350,145 L535,225"></path></g>
<!-- Case tags -->
<text class="case-tag" x="85" y="215">case "apple":</text>
<text class="case-tag" x="235" y="215">case "banana":</text>
<text class="case-tag" x="385" y="215">case "orange":</text>
<text class="case-tag" x="535" y="215">case _:</text>
<!-- Blocks -->
<g id="n-block1">
<rect class="fc-shape fc-block" x="25" y="225" width="120" height="50" rx="8"></rect>
<text class="fc-text on-block" x="85" y="255">๐ Apple</text>
</g>
<g id="n-block2">
<rect class="fc-shape fc-block" x="175" y="225" width="120" height="50" rx="8"></rect>
<text class="fc-text on-block" x="235" y="255">๐ Banana</text>
</g>
<g id="n-block3">
<rect class="fc-shape fc-block" x="325" y="225" width="120" height="50" rx="8"></rect>
<text class="fc-text on-block" x="385" y="255">๐ Orange</text>
</g>
<g id="n-block4">
<rect class="fc-shape fc-block" x="475" y="225" width="120" height="50" rx="8"></rect>
<text class="fc-text on-block" x="535" y="255">โ Unknown</text>
</g>
<!-- Merge lines -->
<g class="fc-edge" id="e-b1-merge"><path d="M85,275 L85,380 L310,380"></path></g>
<g class="fc-edge" id="e-b2-merge"><path d="M235,275 L235,380 L310,380"></path></g>
<g class="fc-edge" id="e-b3-merge"><path d="M385,275 L385,380 L310,380"></path></g>
<g class="fc-edge" id="e-b4-merge"><path d="M535,275 L535,380 L310,380"></path></g>
<!-- Junction -->
<circle class="junction" id="junction" cx="310" cy="380" r="4.5"></circle>
<!-- Junction -> End -->
<g class="fc-edge" id="e-merge-end">
<path d="M310,380 L310,424"></path>
<polygon points="310,430 305,420 315,420"></polygon>
</g>
<!-- End -->
<g id="n-end">
<rect class="fc-shape fc-pill" x="240" y="430" width="140" height="42" rx="21"></rect>
<text class="fc-text on-pill" x="310" y="456">End</text>
</g>
</svg>
</div>
<p class="caption" id="caption"></p>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-pymatch')
|| document.querySelector('.infographic-pymatch');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
const input = wrapper.querySelector('#fruitInput');
const caption = wrapper.querySelector('#caption');
const blocks = {
apple: wrapper.querySelector('#n-block1 .fc-block'),
banana: wrapper.querySelector('#n-block2 .fc-block'),
orange: wrapper.querySelector('#n-block3 .fc-block'),
default: wrapper.querySelector('#n-block4 .fc-block')
};
const fanEdges = {
apple: wrapper.querySelector('#e-sw-b1'),
banana: wrapper.querySelector('#e-sw-b2'),
orange: wrapper.querySelector('#e-sw-b3'),
default: wrapper.querySelector('#e-sw-b4')
};
const mergeEdges = {
apple: wrapper.querySelector('#e-b1-merge'),
banana: wrapper.querySelector('#e-b2-merge'),
orange: wrapper.querySelector('#e-b3-merge'),
default: wrapper.querySelector('#e-b4-merge')
};
const eStartSw = wrapper.querySelector('#e-start-sw');
const eMergeEnd = wrapper.querySelector('#e-merge-end');
const junction = wrapper.querySelector('#junction');
const allEdges = [eStartSw, eMergeEnd, ...Object.values(fanEdges), ...Object.values(mergeEdges)];
function reset() {
Object.values(blocks).forEach(b => b.classList.remove('reached'));
junction.classList.remove('is-taken');
allEdges.forEach(e => e.classList.remove('is-check', 'is-taken'));
}
function update() {
reset();
eStartSw.classList.add('is-check');
const raw = input.value.trim().toLowerCase();
const key = blocks.hasOwnProperty(raw) ? raw : 'default';
fanEdges[key].classList.add('is-check');
blocks[key].classList.add('reached');
mergeEdges[key].classList.add('is-taken');
eMergeEnd.classList.add('is-taken');
junction.classList.add('is-taken');
if (key === 'default') {
caption.innerHTML = `<strong>fruit = "${input.value}"</strong> โ no case matched, case _ runs`;
} else {
caption.innerHTML = `<strong>fruit = "${input.value}"</strong> โ case "${key}" matched`;
}
}
input.addEventListener('input', update);
wrapper.querySelectorAll('.preset-btn').forEach(btn => {
btn.addEventListener('click', () => { input.value = btn.dataset.v; update(); });
});
update();
})();
</script></div>