These special keywords help control what happens inside loops:
Keyword | What It Does |
|---|---|
| Stops the loop immediately |
| Skips the current iteration and moves to the next |
| Does nothing — used as a placeholder when code will be added later |
🔸 break
<div class="infographic-pybreak">
<style>
.infographic-pybreak {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--ok: #1a7f4e;
--ok-soft: #e3f5ec;
--warn: #b45309;
--warn-soft: #fdf0dc;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', -apple-system, sans-serif;
--mono-font: 'IBM Plex Mono', 'Courier New', monospace;
max-width: 820px;
margin: 0 auto;
box-sizing: border-box;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-pybreak[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;
--warn: #e0a458;
--warn-soft: #3a2c14;
}
.infographic-pybreak * { box-sizing: border-box; }
.infographic-pybreak .ig-inner { padding: 1.75rem clamp(1.25rem, 5vw, 3rem) 2rem; }
.infographic-pybreak .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-pybreak .ig-code {
text-align: center; font-family: var(--mono-font); font-size: 0.8rem; color: var(--ink-soft);
margin: 0 0 1.75rem; line-height: 1.6;
}
.infographic-pybreak .ig-code strong { color: var(--warn); }
.infographic-pybreak .controls { display: flex; align-items: center; justify-content: center; gap: 0.6rem; flex-wrap: wrap; }
.infographic-pybreak .ctrl-btn {
font: inherit; font-size: 0.82rem; font-weight: 600; border: 1px solid var(--line);
background: var(--paper-alt); color: var(--ink); padding: 0.45rem 1rem;
border-radius: 999px; cursor: pointer; display: inline-flex; align-items: center; gap: 0.35rem;
}
.infographic-pybreak .ctrl-btn:hover { border-color: var(--accent); color: var(--accent); }
.infographic-pybreak .ctrl-btn.primary { background: var(--accent); color: var(--paper); border-color: var(--accent); }
.infographic-pybreak .i-badge {
font-family: var(--mono-font); font-size: 0.85rem; font-weight: 700; color: var(--accent);
background: var(--accent-soft); padding: 0.45rem 0.9rem; border-radius: 999px;
}
.infographic-pybreak .stage { margin-top: 1.5rem; display: flex; justify-content: center; }
.infographic-pybreak .stage svg { width: 100%; max-width: 720px; height: auto; overflow: visible; }
.infographic-pybreak .fc-shape { fill: var(--paper-alt); stroke: var(--line); stroke-width: 1.8; transition: fill 0.2s, stroke 0.2s; }
.infographic-pybreak .fc-shape.reached-yes { fill: var(--accent-soft); stroke: var(--accent); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pybreak .fc-shape.reached-no { fill: var(--paper-alt); stroke: var(--accent); }
.infographic-pybreak .fc-shape.reached-break { fill: var(--warn-soft); stroke: var(--warn); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pybreak .fc-block.reached { fill: var(--ok-soft); stroke: var(--ok); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pybreak .fc-pill { fill: var(--accent-soft); stroke: var(--accent); }
.infographic-pybreak .fc-pill.reached { filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pybreak .fc-pill.reached-break { fill: var(--warn-soft); stroke: var(--warn); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pybreak .fc-text { font-family: var(--mono-font); font-size: 12px; fill: var(--ink); text-anchor: middle; }
.infographic-pybreak .fc-text.on-pill { fill: var(--accent); font-weight: 700; }
.infographic-pybreak .fc-text.on-block { font-weight: 700; }
.infographic-pybreak .fc-mark { font-family: var(--mono-font); font-size: 13px; font-weight: 700; text-anchor: middle; }
.infographic-pybreak .fc-mark.yes { fill: var(--accent); }
.infographic-pybreak .fc-mark.no { fill: var(--ink-soft); }
.infographic-pybreak .fc-mark.break { fill: var(--warn); }
.infographic-pybreak .edge-label { font-family: var(--mono-font); font-size: 10px; fill: var(--ink-soft); text-anchor: middle; }
.infographic-pybreak .edge-label.warn { fill: var(--warn); font-weight: 700; }
.infographic-pybreak .fc-edge path { stroke: var(--line); stroke-width: 2; fill: none; transition: stroke 0.2s; }
.infographic-pybreak .fc-edge polygon { fill: var(--line); transition: fill 0.2s; }
.infographic-pybreak .fc-edge.is-active path { stroke: var(--accent); stroke-width: 2.5; }
.infographic-pybreak .fc-edge.is-active polygon { fill: var(--accent); }
.infographic-pybreak .fc-edge.is-break path { stroke: var(--warn); stroke-width: 2.5; }
.infographic-pybreak .fc-edge.is-break polygon { fill: var(--warn); }
.infographic-pybreak .junction { fill: var(--line); transition: fill 0.2s; }
.infographic-pybreak .junction.is-active { fill: var(--accent); }
.infographic-pybreak .junction.is-break { fill: var(--warn); }
.infographic-pybreak .output {
margin-top: 1.5rem; text-align: center; font-family: var(--mono-font); font-size: 0.85rem;
color: var(--ink-soft); min-height: 1.4em;
}
.infographic-pybreak .output strong { color: var(--ok); }
.infographic-pybreak .caption {
text-align: center; font-size: 0.9rem; color: var(--ink-soft); margin-top: 0.6rem; min-height: 1.2em;
}
.infographic-pybreak .caption strong { color: var(--ink); font-family: var(--mono-font); }
.infographic-pybreak .caption strong.warn { color: var(--warn); }
@media (prefers-reduced-motion: reduce) {
.infographic-pybreak *, .infographic-pybreak *::before, .infographic-pybreak *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="ig-inner">
<p class="ig-code">for i in range(1, 6):<br> if i == 4: <strong>break</strong><br> print(i)</p>
<div class="controls">
<button class="ctrl-btn primary" id="playBtn">▶ Play</button>
<button class="ctrl-btn" id="restartBtn">⟲ Restart</button>
<span class="i-badge" id="iBadge">i = —</span>
</div>
<div class="stage">
<svg viewBox="0 0 770 420" xmlns="http://www.w3.org/2000/svg">
<!-- Start -->
<g id="n-start">
<rect class="fc-shape fc-pill" x="15" y="130" width="100" height="40" rx="20"></rect>
<text class="fc-text on-pill" x="65" y="155">Start</text>
</g>
<!-- Start -> Init -->
<g class="fc-edge" id="e-start-init">
<path d="M115,150 L149,150"></path>
<polygon points="155,150 145,145 145,155"></polygon>
</g>
<!-- Init -->
<g id="n-init">
<rect class="fc-shape fc-block" x="155" y="125" width="130" height="50" rx="8"></rect>
<text class="fc-text on-block" x="220" y="155">i = 1</text>
</g>
<!-- Init -> Condition1 -->
<g class="fc-edge" id="e-init-check1">
<path d="M285,150 L309,150"></path>
<polygon points="315,150 305,145 305,155"></polygon>
</g>
<!-- Condition 1: i < 6 -->
<g id="n-check1">
<polygon class="fc-shape" points="365,95 435,150 365,205 295,150"></polygon>
<text class="fc-text" x="365" y="146">i < 6</text>
<text class="fc-text" x="365" y="160">?</text>
<text class="fc-mark" id="mark-check1" x="400" y="115"></text>
</g>
<!-- Yes1 -> Break check -->
<g class="fc-edge" id="e-check1-yes">
<path d="M435,150 L459,150"></path>
<polygon points="465,150 455,145 455,155"></polygon>
</g>
<text class="edge-label" x="450" y="138">yes</text>
<!-- Break check: i == 4 -->
<g id="n-breakcheck">
<polygon class="fc-shape" points="535,95 605,150 535,205 465,150"></polygon>
<text class="fc-text" x="535" y="146">i == 4</text>
<text class="fc-text" x="535" y="160">?</text>
<text class="fc-mark" id="mark-breakcheck" x="570" y="115"></text>
</g>
<!-- Break check No -> Statement -->
<g class="fc-edge" id="e-breakcheck-no">
<path d="M605,150 L629,150"></path>
<polygon points="635,150 625,145 625,155"></polygon>
</g>
<text class="edge-label" x="620" y="138">no</text>
<g id="n-statement">
<rect class="fc-shape fc-block" x="635" y="125" width="120" height="50" rx="8"></rect>
<text class="fc-text on-block" x="695" y="155">print(i)</text>
</g>
<!-- Statement -> Increment -->
<g class="fc-edge" id="e-statement-inc">
<path d="M695,125 L695,84"></path>
<polygon points="695,78 690,88 700,88"></polygon>
</g>
<!-- Increment -->
<g id="n-increment">
<rect class="fc-shape fc-block" x="635" y="25" width="120" height="50" rx="8"></rect>
<text class="fc-text on-block" x="695" y="55">i += 1</text>
</g>
<!-- Increment -> Condition1 (loop back) -->
<g class="fc-edge" id="e-inc-check1">
<path d="M635,50 L365,50 L365,84"></path>
<polygon points="365,90 360,80 370,80"></polygon>
</g>
<!-- Break check Yes -> down -> junction (break!) -->
<g class="fc-edge" id="e-breakcheck-yes">
<path d="M535,205 L535,290 L365,290"></path>
</g>
<text class="edge-label warn" x="551" y="240">yes — break!</text>
<!-- Condition1 No -> junction (loop finished normally) -->
<g class="fc-edge" id="e-check1-no">
<path d="M365,205 L365,284"></path>
</g>
<text class="edge-label" x="381" y="240">no</text>
<!-- Junction -->
<circle class="junction" id="junction" cx="365" cy="290" r="4.5"></circle>
<!-- Junction -> End -->
<g class="fc-edge" id="e-junction-end">
<path d="M365,290 L365,334"></path>
<polygon points="365,340 360,330 370,330"></polygon>
</g>
<!-- End -->
<g id="n-end">
<rect class="fc-shape fc-pill" x="315" y="340" width="100" height="40" rx="20"></rect>
<text class="fc-text on-pill" x="365" y="365">End</text>
</g>
</svg>
</div>
<p class="output" id="output"></p>
<p class="caption" id="caption">Press Play to run the loop.</p>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-pybreak')
|| document.querySelector('.infographic-pybreak');
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 playBtn = wrapper.querySelector('#playBtn');
const restartBtn = wrapper.querySelector('#restartBtn');
const iBadge = wrapper.querySelector('#iBadge');
const output = wrapper.querySelector('#output');
const caption = wrapper.querySelector('#caption');
const nStart = wrapper.querySelector('#n-start .fc-pill');
const nInit = wrapper.querySelector('#n-init .fc-block');
const nCheck1 = wrapper.querySelector('#n-check1 .fc-shape');
const markCheck1 = wrapper.querySelector('#mark-check1');
const nBreakCheck = wrapper.querySelector('#n-breakcheck .fc-shape');
const markBreakCheck = wrapper.querySelector('#mark-breakcheck');
const nStatement = wrapper.querySelector('#n-statement .fc-block');
const nIncrement = wrapper.querySelector('#n-increment .fc-block');
const nEnd = wrapper.querySelector('#n-end .fc-pill');
const junction = wrapper.querySelector('#junction');
const eStartInit = wrapper.querySelector('#e-start-init');
const eInitCheck1 = wrapper.querySelector('#e-init-check1');
const eCheck1Yes = wrapper.querySelector('#e-check1-yes');
const eBreakcheckNo = wrapper.querySelector('#e-breakcheck-no');
const eStatementInc = wrapper.querySelector('#e-statement-inc');
const eIncCheck1 = wrapper.querySelector('#e-inc-check1');
const eBreakcheckYes = wrapper.querySelector('#e-breakcheck-yes');
const eCheck1No = wrapper.querySelector('#e-check1-no');
const eJunctionEnd = wrapper.querySelector('#e-junction-end');
const allNodes = [nStart, nInit, nCheck1, nBreakCheck, nStatement, nIncrement, nEnd];
const allEdges = [eStartInit, eInitCheck1, eCheck1Yes, eBreakcheckNo, eStatementInc, eIncCheck1, eBreakcheckYes, eCheck1No, eJunctionEnd];
function resetVisual() {
allNodes.forEach(n => n.classList.remove('reached', 'reached-yes', 'reached-no', 'reached-break'));
allEdges.forEach(e => e.classList.remove('is-active', 'is-break'));
junction.classList.remove('is-active', 'is-break');
markCheck1.textContent = ''; markCheck1.classList.remove('yes', 'no');
markBreakCheck.textContent = ''; markBreakCheck.classList.remove('yes', 'no', 'break');
}
let steps = [];
function buildSteps() {
steps = [];
steps.push({ edge: eStartInit });
steps.push({ node: nInit, setBadge: 1 });
steps.push({ edge: eInitCheck1 });
let i = 1;
let safety = 0;
while (safety++ < 20) {
const cond1 = i < 6;
steps.push({ check1: true, i, result: cond1 });
if (!cond1) {
steps.push({ edge: eCheck1No });
steps.push({ junctionStep: true, viaBreak: false });
steps.push({ edge: eJunctionEnd });
steps.push({ node: nEnd, done: true });
break;
}
steps.push({ edge: eCheck1Yes });
const isBreak = (i === 4);
steps.push({ breakcheck: true, i, result: isBreak });
if (isBreak) {
steps.push({ edge: eBreakcheckYes });
steps.push({ junctionStep: true, viaBreak: true });
steps.push({ edge: eJunctionEnd });
steps.push({ node: nEnd, done: true, viaBreak: true });
break;
}
steps.push({ edge: eBreakcheckNo });
steps.push({ node: nStatement, i, log: i });
steps.push({ edge: eStatementInc });
steps.push({ node: nIncrement, setBadge: i + 1 });
steps.push({ edge: eIncCheck1 });
i++;
}
}
buildSteps();
let idx = -1;
let timer = null;
let logged = [];
function applyStep(step) {
resetVisual();
nStart.classList.add('reached');
if (step.edge) {
step.edge.classList.add(step.edge === eBreakcheckYes || (step.edge === eJunctionEnd && wasBreak) ? 'is-break' : 'is-active');
}
if (step.junctionStep) {
junction.classList.add(step.viaBreak ? 'is-break' : 'is-active');
wasBreak = step.viaBreak;
}
if (step.node) {
step.node.classList.add(step.viaBreak ? 'reached-break' : 'reached');
if (step.setBadge !== undefined) iBadge.textContent = `i = ${step.setBadge}`;
if (step.log !== undefined) {
logged.push(step.log);
output.innerHTML = `output: <strong>${logged.join(', ')}</strong>`;
}
if (step.done) {
caption.innerHTML = step.viaBreak
? `loop exited early via <strong class="warn">break</strong>`
: `loop finished normally — condition is false`;
}
}
if (step.check1) {
nCheck1.classList.add(step.result ? 'reached-yes' : 'reached-no');
markCheck1.textContent = step.result ? '✓' : '✗';
markCheck1.classList.add(step.result ? 'yes' : 'no');
iBadge.textContent = `i = ${step.i}`;
if (!step.result) caption.textContent = `i = ${step.i} → false, exit the loop`;
else caption.textContent = `i = ${step.i} → true, check for break`;
}
if (step.breakcheck) {
nBreakCheck.classList.add(step.result ? 'reached-break' : 'reached-no');
markBreakCheck.textContent = step.result ? '✓' : '✗';
markBreakCheck.classList.add(step.result ? 'break' : 'no');
iBadge.textContent = `i = ${step.i}`;
caption.innerHTML = step.result
? `i = ${step.i} → <strong class="warn">break!</strong> exit loop immediately`
: `i = ${step.i} → not 4, keep going`;
}
}
let wasBreak = false;
function stop() {
clearInterval(timer);
timer = null;
playBtn.textContent = '▶ Play';
}
function advance() {
idx++;
if (idx >= steps.length) {
stop();
return;
}
applyStep(steps[idx]);
if (idx >= steps.length - 1) stop();
}
function play() {
if (timer) { stop(); return; }
if (idx >= steps.length - 1) restart(false);
playBtn.textContent = '⏸ Pause';
timer = setInterval(advance, 850);
advance();
}
function restart(clearBadge = true) {
stop();
idx = -1;
logged = [];
wasBreak = false;
output.textContent = '';
resetVisual();
if (clearBadge) {
iBadge.textContent = 'i = —';
caption.textContent = 'Press Play to run the loop.';
}
}
playBtn.addEventListener('click', play);
restartBtn.addEventListener('click', () => restart(true));
restart(true);
})();
</script></div>for i in range(1, 6):
if i == 3:
break # Stop the loop when i is 3
print(i)🔸 continue
<div class="infographic-pycontinue">
<style>
.infographic-pycontinue {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--ok: #1a7f4e;
--ok-soft: #e3f5ec;
--warn: #b45309;
--warn-soft: #fdf0dc;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', -apple-system, sans-serif;
--mono-font: 'IBM Plex Mono', 'Courier New', monospace;
max-width: 820px;
margin: 0 auto;
box-sizing: border-box;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-pycontinue[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;
--warn: #e0a458;
--warn-soft: #3a2c14;
}
.infographic-pycontinue * { box-sizing: border-box; }
.infographic-pycontinue .ig-inner { padding: 1.75rem clamp(1.25rem, 5vw, 3rem) 2rem; }
.infographic-pycontinue .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-pycontinue .ig-code {
text-align: center; font-family: var(--mono-font); font-size: 0.8rem; color: var(--ink-soft);
margin: 0 0 1.75rem; line-height: 1.6;
}
.infographic-pycontinue .ig-code strong { color: var(--warn); }
.infographic-pycontinue .controls { display: flex; align-items: center; justify-content: center; gap: 0.6rem; flex-wrap: wrap; }
.infographic-pycontinue .ctrl-btn {
font: inherit; font-size: 0.82rem; font-weight: 600; border: 1px solid var(--line);
background: var(--paper-alt); color: var(--ink); padding: 0.45rem 1rem;
border-radius: 999px; cursor: pointer; display: inline-flex; align-items: center; gap: 0.35rem;
}
.infographic-pycontinue .ctrl-btn:hover { border-color: var(--accent); color: var(--accent); }
.infographic-pycontinue .ctrl-btn.primary { background: var(--accent); color: var(--paper); border-color: var(--accent); }
.infographic-pycontinue .i-badge {
font-family: var(--mono-font); font-size: 0.85rem; font-weight: 700; color: var(--accent);
background: var(--accent-soft); padding: 0.45rem 0.9rem; border-radius: 999px;
}
.infographic-pycontinue .stage { margin-top: 1.5rem; display: flex; justify-content: center; }
.infographic-pycontinue .stage svg { width: 100%; max-width: 720px; height: auto; overflow: visible; }
.infographic-pycontinue .fc-shape { fill: var(--paper-alt); stroke: var(--line); stroke-width: 1.8; transition: fill 0.2s, stroke 0.2s; }
.infographic-pycontinue .fc-shape.reached-yes { fill: var(--accent-soft); stroke: var(--accent); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pycontinue .fc-shape.reached-no { fill: var(--paper-alt); stroke: var(--accent); }
.infographic-pycontinue .fc-shape.reached-skip { fill: var(--warn-soft); stroke: var(--warn); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pycontinue .fc-block.reached { fill: var(--ok-soft); stroke: var(--ok); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pycontinue .fc-block.reached-skip { fill: var(--warn-soft); stroke: var(--warn); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pycontinue .fc-pill { fill: var(--accent-soft); stroke: var(--accent); }
.infographic-pycontinue .fc-pill.reached { filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pycontinue .fc-text { font-family: var(--mono-font); font-size: 12px; fill: var(--ink); text-anchor: middle; }
.infographic-pycontinue .fc-text.on-pill { fill: var(--accent); font-weight: 700; }
.infographic-pycontinue .fc-text.on-block { font-weight: 700; }
.infographic-pycontinue .fc-mark { font-family: var(--mono-font); font-size: 13px; font-weight: 700; text-anchor: middle; }
.infographic-pycontinue .fc-mark.yes { fill: var(--accent); }
.infographic-pycontinue .fc-mark.no { fill: var(--ink-soft); }
.infographic-pycontinue .fc-mark.skip { fill: var(--warn); }
.infographic-pycontinue .edge-label { font-family: var(--mono-font); font-size: 10px; fill: var(--ink-soft); text-anchor: middle; }
.infographic-pycontinue .edge-label.warn { fill: var(--warn); font-weight: 700; }
.infographic-pycontinue .fc-edge path { stroke: var(--line); stroke-width: 2; fill: none; transition: stroke 0.2s; }
.infographic-pycontinue .fc-edge polygon { fill: var(--line); transition: fill 0.2s; }
.infographic-pycontinue .fc-edge.is-active path { stroke: var(--accent); stroke-width: 2.5; }
.infographic-pycontinue .fc-edge.is-active polygon { fill: var(--accent); }
.infographic-pycontinue .fc-edge.is-skip path { stroke: var(--warn); stroke-width: 2.5; }
.infographic-pycontinue .fc-edge.is-skip polygon { fill: var(--warn); }
.infographic-pycontinue .output {
margin-top: 1.5rem; text-align: center; font-family: var(--mono-font); font-size: 0.85rem;
color: var(--ink-soft); min-height: 1.4em;
}
.infographic-pycontinue .output strong { color: var(--ok); }
.infographic-pycontinue .caption {
text-align: center; font-size: 0.9rem; color: var(--ink-soft); margin-top: 0.6rem; min-height: 1.2em;
}
.infographic-pycontinue .caption strong { color: var(--ink); font-family: var(--mono-font); }
.infographic-pycontinue .caption strong.warn { color: var(--warn); }
@media (prefers-reduced-motion: reduce) {
.infographic-pycontinue *, .infographic-pycontinue *::before, .infographic-pycontinue *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="ig-inner">
<p class="ig-code">for i in range(10):<br> if i % 2 == 0: <strong>continue</strong><br> print(i)</p>
<div class="controls">
<button class="ctrl-btn primary" id="playBtn">▶ Play</button>
<button class="ctrl-btn" id="restartBtn">⟲ Restart</button>
<span class="i-badge" id="iBadge">i = —</span>
</div>
<div class="stage">
<svg viewBox="0 0 770 350" xmlns="http://www.w3.org/2000/svg">
<!-- Start -->
<g id="n-start">
<rect class="fc-shape fc-pill" x="15" y="130" width="100" height="40" rx="20"></rect>
<text class="fc-text on-pill" x="65" y="155">Start</text>
</g>
<!-- Start -> Init -->
<g class="fc-edge" id="e-start-init">
<path d="M115,150 L149,150"></path>
<polygon points="155,150 145,145 145,155"></polygon>
</g>
<!-- Init -->
<g id="n-init">
<rect class="fc-shape fc-block" x="155" y="125" width="130" height="50" rx="8"></rect>
<text class="fc-text on-block" x="220" y="155">i = 0</text>
</g>
<!-- Init -> Condition1 -->
<g class="fc-edge" id="e-init-check1">
<path d="M285,150 L309,150"></path>
<polygon points="315,150 305,145 305,155"></polygon>
</g>
<!-- Condition 1: i < 10 -->
<g id="n-check1">
<polygon class="fc-shape" points="365,95 435,150 365,205 295,150"></polygon>
<text class="fc-text" x="365" y="146">i < 10</text>
<text class="fc-text" x="365" y="160">?</text>
<text class="fc-mark" id="mark-check1" x="400" y="115"></text>
</g>
<!-- Yes1 -> Continue check -->
<g class="fc-edge" id="e-check1-yes">
<path d="M435,150 L459,150"></path>
<polygon points="465,150 455,145 455,155"></polygon>
</g>
<text class="edge-label" x="450" y="138">yes</text>
<!-- Continue check: i % 2 == 0 -->
<g id="n-continuecheck">
<polygon class="fc-shape" points="535,95 605,150 535,205 465,150"></polygon>
<text class="fc-text" x="535" y="141">i % 2</text>
<text class="fc-text" x="535" y="155">== 0 ?</text>
<text class="fc-mark" id="mark-continuecheck" x="570" y="115"></text>
</g>
<!-- Continue check No (odd) -> Statement -->
<g class="fc-edge" id="e-cc-no">
<path d="M605,150 L629,150"></path>
<polygon points="635,150 625,145 625,155"></polygon>
</g>
<text class="edge-label" x="620" y="138">no</text>
<g id="n-statement">
<rect class="fc-shape fc-block" x="635" y="125" width="120" height="50" rx="8"></rect>
<text class="fc-text on-block" x="695" y="155">print(i)</text>
</g>
<!-- Statement -> Increment -->
<g class="fc-edge" id="e-statement-inc">
<path d="M695,125 L695,84"></path>
<polygon points="695,78 690,88 700,88"></polygon>
</g>
<!-- Increment -->
<g id="n-increment">
<rect class="fc-shape fc-block" x="635" y="25" width="120" height="50" rx="8"></rect>
<text class="fc-text on-block" x="695" y="55">i += 1</text>
</g>
<!-- Continue check Yes (even) -> down and back to Condition1, skipping Statement/Increment display -->
<g class="fc-edge" id="e-cc-yes">
<path d="M535,205 L535,245 L365,245 L365,211"></path>
<polygon points="365,205 360,211 370,211"></polygon>
</g>
<text class="edge-label warn" x="450" y="260">yes — continue!</text>
<!-- Increment -> Condition1 (loop back) -->
<g class="fc-edge" id="e-inc-check1">
<path d="M635,50 L365,50 L365,84"></path>
<polygon points="365,90 360,80 370,80"></polygon>
</g>
<!-- Condition1 No -> End -->
<g class="fc-edge" id="e-check1-no">
<path d="M365,205 L365,274"></path>
<polygon points="365,280 360,270 370,270"></polygon>
</g>
<text class="edge-label" x="381" y="240">no</text>
<!-- End -->
<g id="n-end">
<rect class="fc-shape fc-pill" x="315" y="280" width="100" height="40" rx="20"></rect>
<text class="fc-text on-pill" x="365" y="305">End</text>
</g>
</svg>
</div>
<p class="output" id="output"></p>
<p class="caption" id="caption">Press Play to run the loop.</p>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-pycontinue')
|| document.querySelector('.infographic-pycontinue');
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 playBtn = wrapper.querySelector('#playBtn');
const restartBtn = wrapper.querySelector('#restartBtn');
const iBadge = wrapper.querySelector('#iBadge');
const output = wrapper.querySelector('#output');
const caption = wrapper.querySelector('#caption');
const nStart = wrapper.querySelector('#n-start .fc-pill');
const nInit = wrapper.querySelector('#n-init .fc-block');
const nCheck1 = wrapper.querySelector('#n-check1 .fc-shape');
const markCheck1 = wrapper.querySelector('#mark-check1');
const nContinueCheck = wrapper.querySelector('#n-continuecheck .fc-shape');
const markContinueCheck = wrapper.querySelector('#mark-continuecheck');
const nStatement = wrapper.querySelector('#n-statement .fc-block');
const nIncrement = wrapper.querySelector('#n-increment .fc-block');
const nEnd = wrapper.querySelector('#n-end .fc-pill');
const eStartInit = wrapper.querySelector('#e-start-init');
const eInitCheck1 = wrapper.querySelector('#e-init-check1');
const eCheck1Yes = wrapper.querySelector('#e-check1-yes');
const eCcNo = wrapper.querySelector('#e-cc-no');
const eStatementInc = wrapper.querySelector('#e-statement-inc');
const eIncCheck1 = wrapper.querySelector('#e-inc-check1');
const eCcYes = wrapper.querySelector('#e-cc-yes');
const eCheck1No = wrapper.querySelector('#e-check1-no');
const allNodes = [nStart, nInit, nCheck1, nContinueCheck, nStatement, nIncrement, nEnd];
const allEdges = [eStartInit, eInitCheck1, eCheck1Yes, eCcNo, eStatementInc, eIncCheck1, eCcYes, eCheck1No];
function resetVisual() {
allNodes.forEach(n => n.classList.remove('reached', 'reached-yes', 'reached-no', 'reached-skip'));
allEdges.forEach(e => e.classList.remove('is-active', 'is-skip'));
markCheck1.textContent = ''; markCheck1.classList.remove('yes', 'no');
markContinueCheck.textContent = ''; markContinueCheck.classList.remove('yes', 'no', 'skip');
}
let steps = [];
function buildSteps() {
steps = [];
steps.push({ edge: eStartInit });
steps.push({ node: nInit, setBadge: 0 });
steps.push({ edge: eInitCheck1 });
let i = 0;
let safety = 0;
while (safety++ < 40) {
const cond1 = i < 10;
steps.push({ check1: true, i, result: cond1 });
if (!cond1) {
steps.push({ edge: eCheck1No });
steps.push({ node: nEnd, done: true });
break;
}
steps.push({ edge: eCheck1Yes });
const isEven = (i % 2 === 0);
steps.push({ ccheck: true, i, result: isEven });
if (isEven) {
steps.push({ edge: eCcYes, skip: true });
} else {
steps.push({ edge: eCcNo });
steps.push({ node: nStatement, i, log: i });
steps.push({ edge: eStatementInc });
steps.push({ node: nIncrement, setBadge: i + 1 });
steps.push({ edge: eIncCheck1 });
}
i++;
}
}
buildSteps();
let idx = -1;
let timer = null;
let logged = [];
function applyStep(step) {
resetVisual();
nStart.classList.add('reached');
if (step.edge) {
step.edge.classList.add(step.skip ? 'is-skip' : 'is-active');
}
if (step.node) {
if (step.skip) {
step.node.classList.add('reached-skip');
} else {
step.node.classList.add('reached');
}
if (step.setBadge !== undefined) iBadge.textContent = `i = ${step.setBadge}`;
if (step.log !== undefined) {
logged.push(step.log);
output.innerHTML = `output: <strong>${logged.join(', ')}</strong>`;
}
if (step.done) {
caption.textContent = 'Loop finished — condition is false.';
}
}
if (step.check1) {
nCheck1.classList.add(step.result ? 'reached-yes' : 'reached-no');
markCheck1.textContent = step.result ? '✓' : '✗';
markCheck1.classList.add(step.result ? 'yes' : 'no');
iBadge.textContent = `i = ${step.i}`;
caption.textContent = step.result
? `i = ${step.i} → true, check for even`
: `i = ${step.i} → false, exit the loop`;
}
if (step.ccheck) {
nContinueCheck.classList.add(step.result ? 'reached-skip' : 'reached-no');
markContinueCheck.textContent = step.result ? '✓' : '✗';
markContinueCheck.classList.add(step.result ? 'skip' : 'no');
iBadge.textContent = `i = ${step.i}`;
caption.innerHTML = step.result
? `i = ${step.i} → even, <strong class="warn">continue!</strong> jump back to the condition`
: `i = ${step.i} → odd, print it`;
}
}
function stop() {
clearInterval(timer);
timer = null;
playBtn.textContent = '▶ Play';
}
function advance() {
idx++;
if (idx >= steps.length) {
stop();
return;
}
applyStep(steps[idx]);
if (idx >= steps.length - 1) stop();
}
function play() {
if (timer) { stop(); return; }
if (idx >= steps.length - 1) restart(false);
playBtn.textContent = '⏸ Pause';
timer = setInterval(advance, 700);
advance();
}
function restart(clearBadge = true) {
stop();
idx = -1;
logged = [];
output.textContent = '';
resetVisual();
if (clearBadge) {
iBadge.textContent = 'i = —';
caption.textContent = 'Press Play to run the loop.';
}
}
playBtn.addEventListener('click', play);
restartBtn.addEventListener('click', () => restart(true));
restart(true);
})();
</script></div>for i in range(1, 6):
if i == 3:
continue # Skip this iteration when i is 3
print(i)🔸 pass
<div class="infographic-pypass">
<style>
.infographic-pypass {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--ok: #1a7f4e;
--ok-soft: #e3f5ec;
--pass: #6b7280;
--pass-soft: #eceef1;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', -apple-system, sans-serif;
--mono-font: 'IBM Plex Mono', 'Courier New', monospace;
max-width: 820px;
margin: 0 auto;
box-sizing: border-box;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-pypass[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;
--pass: #a3a7ae;
--pass-soft: #2a2c30;
}
.infographic-pypass * { box-sizing: border-box; }
.infographic-pypass .ig-inner { padding: 1.75rem clamp(1.25rem, 5vw, 3rem) 2rem; }
.infographic-pypass .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-pypass .ig-code {
text-align: center; font-family: var(--mono-font); font-size: 0.8rem; color: var(--ink-soft);
margin: 0 0 0.4rem; line-height: 1.6;
}
.infographic-pypass .ig-code strong { color: var(--pass); }
.infographic-pypass .ig-subnote {
text-align: center; font-size: 0.76rem; color: var(--ink-soft); margin: 0 0 1.5rem;
}
.infographic-pypass .controls { display: flex; align-items: center; justify-content: center; gap: 0.6rem; flex-wrap: wrap; }
.infographic-pypass .ctrl-btn {
font: inherit; font-size: 0.82rem; font-weight: 600; border: 1px solid var(--line);
background: var(--paper-alt); color: var(--ink); padding: 0.45rem 1rem;
border-radius: 999px; cursor: pointer; display: inline-flex; align-items: center; gap: 0.35rem;
}
.infographic-pypass .ctrl-btn:hover { border-color: var(--accent); color: var(--accent); }
.infographic-pypass .ctrl-btn.primary { background: var(--accent); color: var(--paper); border-color: var(--accent); }
.infographic-pypass .i-badge {
font-family: var(--mono-font); font-size: 0.85rem; font-weight: 700; color: var(--accent);
background: var(--accent-soft); padding: 0.45rem 0.9rem; border-radius: 999px;
}
.infographic-pypass .stage { margin-top: 1.5rem; display: flex; justify-content: center; }
.infographic-pypass .stage svg { width: 100%; max-width: 720px; height: auto; overflow: visible; }
.infographic-pypass .fc-shape { fill: var(--paper-alt); stroke: var(--line); stroke-width: 1.8; transition: fill 0.2s, stroke 0.2s; }
.infographic-pypass .fc-shape.reached-yes { fill: var(--accent-soft); stroke: var(--accent); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pypass .fc-shape.reached-no { fill: var(--paper-alt); stroke: var(--accent); }
.infographic-pypass .fc-shape.reached-pass { fill: var(--pass-soft); stroke: var(--pass); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pypass .fc-block.reached { fill: var(--ok-soft); stroke: var(--ok); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pypass .fc-block.reached-pass { fill: var(--pass-soft); stroke: var(--pass); filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pypass .fc-pill { fill: var(--accent-soft); stroke: var(--accent); }
.infographic-pypass .fc-pill.reached { filter: drop-shadow(0 3px 6px rgba(0,0,0,0.15)); }
.infographic-pypass .fc-text { font-family: var(--mono-font); font-size: 12px; fill: var(--ink); text-anchor: middle; }
.infographic-pypass .fc-text.on-pill { fill: var(--accent); font-weight: 700; }
.infographic-pypass .fc-text.on-block { font-weight: 700; }
.infographic-pypass .fc-text.on-pass { fill: var(--pass); font-weight: 700; font-style: italic; }
.infographic-pypass .fc-mark { font-family: var(--mono-font); font-size: 13px; font-weight: 700; text-anchor: middle; }
.infographic-pypass .fc-mark.yes { fill: var(--accent); }
.infographic-pypass .fc-mark.no { fill: var(--ink-soft); }
.infographic-pypass .fc-mark.pass { fill: var(--pass); }
.infographic-pypass .edge-label { font-family: var(--mono-font); font-size: 10px; fill: var(--ink-soft); text-anchor: middle; }
.infographic-pypass .edge-label.pass { fill: var(--pass); font-weight: 700; }
.infographic-pypass .fc-edge path { stroke: var(--line); stroke-width: 2; fill: none; transition: stroke 0.2s; }
.infographic-pypass .fc-edge polygon { fill: var(--line); transition: fill 0.2s; }
.infographic-pypass .fc-edge.is-active path { stroke: var(--accent); stroke-width: 2.5; }
.infographic-pypass .fc-edge.is-active polygon { fill: var(--accent); }
.infographic-pypass .fc-edge.is-pass path { stroke: var(--pass); stroke-width: 2.5; stroke-dasharray: 5 4; }
.infographic-pypass .fc-edge.is-pass polygon { fill: var(--pass); }
.infographic-pypass .output {
margin-top: 1.5rem; text-align: center; font-family: var(--mono-font); font-size: 0.85rem;
color: var(--ink-soft); min-height: 1.4em;
}
.infographic-pypass .output strong { color: var(--ok); }
.infographic-pypass .caption {
text-align: center; font-size: 0.9rem; color: var(--ink-soft); margin-top: 0.6rem; min-height: 1.2em;
}
.infographic-pypass .caption strong { color: var(--ink); font-family: var(--mono-font); }
.infographic-pypass .caption strong.pass { color: var(--pass); }
@media (prefers-reduced-motion: reduce) {
.infographic-pypass *, .infographic-pypass *::before, .infographic-pypass *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="ig-inner">
<p class="ig-code">for i in range(5):<br> if i == 2: <strong>pass</strong><br> print(i)</p>
<p class="ig-subnote">pass is a placeholder — it does nothing and skips nothing. Watch print(i) run every time.</p>
<div class="controls">
<button class="ctrl-btn primary" id="playBtn">▶ Play</button>
<button class="ctrl-btn" id="restartBtn">⟲ Restart</button>
<span class="i-badge" id="iBadge">i = —</span>
</div>
<div class="stage">
<svg viewBox="0 0 770 380" xmlns="http://www.w3.org/2000/svg">
<!-- Start -->
<g id="n-start">
<rect class="fc-shape fc-pill" x="15" y="130" width="100" height="40" rx="20"></rect>
<text class="fc-text on-pill" x="65" y="155">Start</text>
</g>
<!-- Start -> Init -->
<g class="fc-edge" id="e-start-init">
<path d="M115,150 L149,150"></path>
<polygon points="155,150 145,145 145,155"></polygon>
</g>
<!-- Init -->
<g id="n-init">
<rect class="fc-shape fc-block" x="155" y="125" width="130" height="50" rx="8"></rect>
<text class="fc-text on-block" x="220" y="155">i = 0</text>
</g>
<!-- Init -> Condition1 -->
<g class="fc-edge" id="e-init-check1">
<path d="M285,150 L309,150"></path>
<polygon points="315,150 305,145 305,155"></polygon>
</g>
<!-- Condition 1: i < 5 -->
<g id="n-check1">
<polygon class="fc-shape" points="365,95 435,150 365,205 295,150"></polygon>
<text class="fc-text" x="365" y="146">i < 5</text>
<text class="fc-text" x="365" y="160">?</text>
<text class="fc-mark" id="mark-check1" x="400" y="115"></text>
</g>
<!-- Yes1 -> Pass check -->
<g class="fc-edge" id="e-check1-yes">
<path d="M435,150 L459,150"></path>
<polygon points="465,150 455,145 455,155"></polygon>
</g>
<text class="edge-label" x="450" y="138">yes</text>
<!-- Pass check: i == 2 -->
<g id="n-passcheck">
<polygon class="fc-shape" points="535,95 605,150 535,205 465,150"></polygon>
<text class="fc-text" x="535" y="146">i == 2</text>
<text class="fc-text" x="535" y="160">?</text>
<text class="fc-mark" id="mark-passcheck" x="570" y="115"></text>
</g>
<!-- Pass check No -> Statement (direct) -->
<g class="fc-edge" id="e-pc-no">
<path d="M605,150 L629,150"></path>
<polygon points="635,150 625,145 625,155"></polygon>
</g>
<text class="edge-label" x="620" y="138">no</text>
<!-- Statement -->
<g id="n-statement">
<rect class="fc-shape fc-block" x="635" y="125" width="120" height="50" rx="8"></rect>
<text class="fc-text on-block" x="695" y="155">print(i)</text>
</g>
<!-- Pass check Yes -> down to Pass box -->
<g class="fc-edge is-pass" id="e-pc-yes">
<path d="M535,205 L535,247 L500,247"></path>
<polygon points="494,247 504,242 504,252"></polygon>
</g>
<text class="edge-label pass" x="551" y="235">yes — pass</text>
<!-- Pass box (does nothing) -->
<g id="n-pass">
<rect class="fc-shape fc-block" x="380" y="225" width="115" height="45" rx="8"></rect>
<text class="fc-text on-pass" x="437" y="252">pass</text>
</g>
<!-- Pass box -> merges back into Statement (fallthrough, nothing skipped) -->
<g class="fc-edge is-pass" id="e-pass-merge">
<path d="M495,247 L695,247 L695,179"></path>
<polygon points="695,173 690,183 700,183"></polygon>
</g>
<!-- Statement -> Increment -->
<g class="fc-edge" id="e-statement-inc">
<path d="M695,125 L695,84"></path>
<polygon points="695,78 690,88 700,88"></polygon>
</g>
<!-- Increment -->
<g id="n-increment">
<rect class="fc-shape fc-block" x="635" y="25" width="120" height="50" rx="8"></rect>
<text class="fc-text on-block" x="695" y="55">i += 1</text>
</g>
<!-- Increment -> Condition1 (loop back) -->
<g class="fc-edge" id="e-inc-check1">
<path d="M635,50 L365,50 L365,84"></path>
<polygon points="365,90 360,80 370,80"></polygon>
</g>
<!-- Condition1 No -> End -->
<g class="fc-edge" id="e-check1-no">
<path d="M365,205 L365,274"></path>
<polygon points="365,280 360,270 370,270"></polygon>
</g>
<text class="edge-label" x="381" y="240">no</text>
<!-- End -->
<g id="n-end">
<rect class="fc-shape fc-pill" x="315" y="280" width="100" height="40" rx="20"></rect>
<text class="fc-text on-pill" x="365" y="305">End</text>
</g>
</svg>
</div>
<p class="output" id="output"></p>
<p class="caption" id="caption">Press Play to run the loop.</p>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-pypass')
|| document.querySelector('.infographic-pypass');
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 playBtn = wrapper.querySelector('#playBtn');
const restartBtn = wrapper.querySelector('#restartBtn');
const iBadge = wrapper.querySelector('#iBadge');
const output = wrapper.querySelector('#output');
const caption = wrapper.querySelector('#caption');
const nStart = wrapper.querySelector('#n-start .fc-pill');
const nInit = wrapper.querySelector('#n-init .fc-block');
const nCheck1 = wrapper.querySelector('#n-check1 .fc-shape');
const markCheck1 = wrapper.querySelector('#mark-check1');
const nPassCheck = wrapper.querySelector('#n-passcheck .fc-shape');
const markPassCheck = wrapper.querySelector('#mark-passcheck');
const nPass = wrapper.querySelector('#n-pass .fc-block');
const nStatement = wrapper.querySelector('#n-statement .fc-block');
const nIncrement = wrapper.querySelector('#n-increment .fc-block');
const nEnd = wrapper.querySelector('#n-end .fc-pill');
const eStartInit = wrapper.querySelector('#e-start-init');
const eInitCheck1 = wrapper.querySelector('#e-init-check1');
const eCheck1Yes = wrapper.querySelector('#e-check1-yes');
const ePcNo = wrapper.querySelector('#e-pc-no');
const ePcYes = wrapper.querySelector('#e-pc-yes');
const ePassMerge = wrapper.querySelector('#e-pass-merge');
const eStatementInc = wrapper.querySelector('#e-statement-inc');
const eIncCheck1 = wrapper.querySelector('#e-inc-check1');
const eCheck1No = wrapper.querySelector('#e-check1-no');
const allNodes = [nStart, nInit, nCheck1, nPassCheck, nPass, nStatement, nIncrement, nEnd];
const allEdges = [eStartInit, eInitCheck1, eCheck1Yes, ePcNo, ePcYes, ePassMerge, eStatementInc, eIncCheck1, eCheck1No];
function resetVisual() {
allNodes.forEach(n => n.classList.remove('reached', 'reached-yes', 'reached-no', 'reached-pass'));
allEdges.forEach(e => e.classList.remove('is-active'));
markCheck1.textContent = ''; markCheck1.classList.remove('yes', 'no');
markPassCheck.textContent = ''; markPassCheck.classList.remove('yes', 'no', 'pass');
}
let steps = [];
function buildSteps() {
steps = [];
steps.push({ edge: eStartInit });
steps.push({ node: nInit, setBadge: 0 });
steps.push({ edge: eInitCheck1 });
let i = 0;
let safety = 0;
while (safety++ < 40) {
const cond1 = i < 5;
steps.push({ check1: true, i, result: cond1 });
if (!cond1) {
steps.push({ edge: eCheck1No });
steps.push({ node: nEnd, done: true });
break;
}
steps.push({ edge: eCheck1Yes });
const isPass = (i === 2);
steps.push({ pcheck: true, i, result: isPass });
if (isPass) {
steps.push({ edge: ePcYes });
steps.push({ node: nPass, i, passHit: true });
steps.push({ edge: ePassMerge });
} else {
steps.push({ edge: ePcNo });
}
steps.push({ node: nStatement, i, print: i, viaPass: isPass });
steps.push({ edge: eStatementInc });
steps.push({ node: nIncrement, setBadge: i + 1 });
steps.push({ edge: eIncCheck1 });
i++;
}
}
buildSteps();
let idx = -1;
let timer = null;
let printed = [];
function applyStep(step) {
resetVisual();
nStart.classList.add('reached');
if (step.edge) {
step.edge.classList.add('is-active');
}
if (step.node) {
if (step.passHit) {
step.node.classList.add('reached-pass');
} else {
step.node.classList.add('reached');
}
if (step.setBadge !== undefined) iBadge.textContent = `i = ${step.setBadge}`;
if (step.print !== undefined) {
printed.push(step.print);
output.innerHTML = `output: <strong>${printed.join(', ')}</strong>`;
}
if (step.passHit) {
caption.innerHTML = `i = ${step.i} → <strong class="pass">pass</strong> runs — literally nothing happens.`;
} else if (step.print !== undefined) {
caption.textContent = step.viaPass
? `print(i) still runs — pass didn't skip it.`
: `i = ${step.i} → not 2, print(i) runs as normal.`;
}
if (step.done) {
caption.textContent = 'Loop finished — every value from 0 to 4 got printed.';
}
}
if (step.check1) {
nCheck1.classList.add(step.result ? 'reached-yes' : 'reached-no');
markCheck1.textContent = step.result ? '✓' : '✗';
markCheck1.classList.add(step.result ? 'yes' : 'no');
iBadge.textContent = `i = ${step.i}`;
caption.textContent = step.result
? `i = ${step.i} → true, check the if`
: `i = ${step.i} → false, exit the loop`;
}
if (step.pcheck) {
nPassCheck.classList.add(step.result ? 'reached-pass' : 'reached-no');
markPassCheck.textContent = step.result ? '•' : '✗';
markPassCheck.classList.add(step.result ? 'pass' : 'no');
iBadge.textContent = `i = ${step.i}`;
caption.innerHTML = step.result
? `i = ${step.i} → matches, but <strong class="pass">pass</strong> does nothing`
: `i = ${step.i} → no match, go straight to print(i)`;
}
}
function stop() {
clearInterval(timer);
timer = null;
playBtn.textContent = '▶ Play';
}
function advance() {
idx++;
if (idx >= steps.length) {
stop();
return;
}
applyStep(steps[idx]);
if (idx >= steps.length - 1) stop();
}
function play() {
if (timer) { stop(); return; }
if (idx >= steps.length - 1) restart(false);
playBtn.textContent = '⏸ Pause';
timer = setInterval(advance, 750);
advance();
}
function restart(clearBadge = true) {
stop();
idx = -1;
printed = [];
output.textContent = '';
resetVisual();
if (clearBadge) {
iBadge.textContent = 'i = —';
caption.textContent = 'Press Play to run the loop.';
}
}
playBtn.addEventListener('click', play);
restartBtn.addEventListener('click', () => restart(true));
restart(true);
})();
</script></div>for i in range(5):
if i == 2: pass # Will pass when i == 2
print(i)📝 pass is useful when you're still writing your program and need to leave a "to-do" in the structure without causing a syntax error.