Skip to content

Instantly share code, notes, and snippets.

@lassebenni
Created January 13, 2026 19:16
Show Gist options
  • Select an option

  • Save lassebenni/e7a4285caa3132265790030e28bfc81b to your computer and use it in GitHub Desktop.

Select an option

Save lassebenni/e7a4285caa3132265790030e28bfc81b to your computer and use it in GitHub Desktop.
Animation: Mutable vs Immutable Types in Python (v4 - Fixed Alignment)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mutable vs Immutable</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #0d1117;
font-family: 'Segoe UI', system-ui, sans-serif;
}
svg { max-width: 100%; height: auto; }
.title { font-size: 18px; fill: #c9d1d9; font-weight: 600; }
.subtitle { font-size: 11px; fill: #8b949e; }
.label { font-family: 'JetBrains Mono', monospace; font-size: 13px; fill: #c9d1d9; }
.code { font-family: 'JetBrains Mono', monospace; font-size: 12px; fill: #79c0ff; }
.value { font-family: 'JetBrains Mono', monospace; font-size: 12px; fill: #0d1117; }
.section-title { font-size: 14px; fill: #c9d1d9; font-weight: 600; }
/* List animation - appending works */
.list-item-new { animation: slideIn 0.6s ease-out 1.5s forwards; opacity: 0; }
.list-check { animation: fadeIn 0.4s ease-out 2.2s forwards; opacity: 0; }
.list-code-2 { animation: fadeIn 0.4s ease-out 1s forwards; opacity: 0; }
.list-result { animation: fadeIn 0.4s ease-out 2s forwards; opacity: 0; }
/* String animation - creates new value */
.string-arrow { animation: drawArrow 0.5s ease-out 3s forwards; stroke-dasharray: 80; stroke-dashoffset: 80; }
.string-new { animation: fadeIn 0.4s ease-out 3.5s forwards; opacity: 0; }
.string-note { animation: fadeIn 0.4s ease-out 4s forwards; opacity: 0; }
.string-code-2 { animation: fadeIn 0.4s ease-out 2.5s forwards; opacity: 0; }
@keyframes slideIn {
from { opacity: 0; transform: translateX(-20px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes fadeIn {
to { opacity: 1; }
}
@keyframes drawArrow {
to { stroke-dashoffset: 0; }
}
</style>
</head>
<body>
<svg viewBox="0 0 600 380" xmlns="http://www.w3.org/2000/svg">
<rect width="600" height="380" fill="#0d1117"/>
<!-- Title -->
<text x="300" y="30" text-anchor="middle" class="title">Mutable vs Immutable Types</text>
<!-- Divider -->
<line x1="300" y1="50" x2="300" y2="360" stroke="#30363d" stroke-width="1" stroke-dasharray="4"/>
<!-- LEFT: Mutable (List) -->
<g transform="translate(15, 55)">
<text x="130" y="15" text-anchor="middle" class="section-title">βœ… Lists are Mutable</text>
<text x="130" y="32" text-anchor="middle" class="subtitle">Can be changed in place</text>
<!-- Code line 1 -->
<text x="10" y="65" class="code">fruits = ["🍎", "🍌"]</text>
<!-- Original list visualization -->
<g transform="translate(10, 80)">
<rect x="0" y="0" width="50" height="40" rx="4" fill="#7ee787"/>
<text x="25" y="26" text-anchor="middle" class="value" font-size="18">🍎</text>
<rect x="58" y="0" width="50" height="40" rx="4" fill="#7ee787"/>
<text x="83" y="26" text-anchor="middle" class="value" font-size="18">🍌</text>
<!-- Empty slot -->
<rect x="116" y="0" width="50" height="40" rx="4" fill="none" stroke="#30363d" stroke-width="2" stroke-dasharray="4"/>
</g>
<!-- Code line 2 -->
<text x="10" y="150" class="code list-code-2">fruits.append("πŸ’")</text>
<!-- Result after append -->
<g class="list-result" transform="translate(10, 165)">
<rect x="0" y="0" width="50" height="40" rx="4" fill="#7ee787"/>
<text x="25" y="26" text-anchor="middle" class="value" font-size="18">🍎</text>
<rect x="58" y="0" width="50" height="40" rx="4" fill="#7ee787"/>
<text x="83" y="26" text-anchor="middle" class="value" font-size="18">🍌</text>
<rect x="116" y="0" width="50" height="40" rx="4" fill="#ffa657"/>
<text x="141" y="26" text-anchor="middle" class="value" font-size="18">πŸ’</text>
</g>
<!-- Check mark -->
<g class="list-check" transform="translate(190, 175)">
<circle cx="18" cy="18" r="18" fill="#238636"/>
<path d="M 10 18 L 16 24 L 26 12" stroke="white" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<text x="10" y="245" class="label list-check">Same object modified!</text>
</g>
<!-- RIGHT: Immutable (String) -->
<g transform="translate(315, 55)">
<text x="130" y="15" text-anchor="middle" class="section-title">πŸ”’ Strings are Immutable</text>
<text x="130" y="32" text-anchor="middle" class="subtitle">Cannot be changed β€” creates new</text>
<!-- Code line 1 -->
<text x="10" y="65" class="code">name = "alice"</text>
<!-- Original string -->
<g transform="translate(10, 80)">
<rect x="0" y="0" width="130" height="40" rx="4" fill="#a5d6ff"/>
<text x="65" y="26" text-anchor="middle" class="value">"alice"</text>
</g>
<!-- Code line 2 -->
<text x="10" y="150" class="code string-code-2">name = name.upper()</text>
<!-- Connection from top box to code -->
<line x1="75" y1="120" x2="75" y2="138" stroke="#30363d" stroke-width="2" stroke-dasharray="4" />
<!-- Arrow from code to new box -->
<path class="string-arrow" d="M 75 160 L 75 195" stroke="#f0883e" stroke-width="2" marker-end="url(#arrowhead-orange)"/>
<!-- New string (Moved down to y=200) -->
<g class="string-new" transform="translate(10, 200)">
<rect x="0" y="0" width="130" height="40" rx="4" fill="#ffa657"/>
<text x="65" y="26" text-anchor="middle" class="value">"ALICE"</text>
</g>
<!-- Note (Moved down) -->
<text x="10" y="275" class="label string-note">New object created!</text>
<text x="10" y="295" class="subtitle string-note">Original "alice" still exists</text>
<text x="10" y="310" class="subtitle string-note">(until garbage collected)</text>
</g>
<!-- Arrowhead -->
<defs>
<marker id="arrowhead-orange" markerWidth="10" markerHeight="7" refX="5" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#f0883e"/>
</marker>
</defs>
</svg>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment