A tuple is an ordered, immutable (unchangeable) collection of items. Once created, its values cannot be altered.
coordinates = (10.5, 20.3)π Why Use Tuples?
You want to protect data from being modified.
Useful for fixed collections, like dates, coordinates, RGB values, etc.
Faster and more memory-efficient than lists.
π Tuple Characteristics
t = (1, 2, 3)
print(t[1]) # β
Accessing second element β 2
# t[0] = 10 # β TypeError: 'tuple' object does not support item assignmentβ Indexed (like lists)
β Cannot be changed
β Can contain mixed data types
π Looping Through a Tuple
for value in t:
print(value)1
2
3π¦ Tuple with One Element?
You need a comma to define a single-element tuple:
x = (5) # This is just an int
y = (5,) # β
This is a tupleπ§ Tuple vs List
Feature | List ( | Tuple ( |
|---|---|---|
Mutable | β Yes | β No |
Speed | Slower | Faster |
Use case | Changing data | Fixed data |
π‘ Real-life Analogy
A tuple is like a passport record β once issued, you canβt change the name, date of birth, etc.
A list is like a shopping list β you can add, remove, or reorder items anytime.
β¨ Bonus: Tuple Unpacking
name, age = ("Alice", 30)
print(name) # Alice
print(age) # 30<div class="infographic-pytuple">
<style>
.infographic-pytuple {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--error: #c0392b;
--error-soft: #fbe9e7;
--mono-font: 'IBM Plex Mono', 'SFMono-Regular', Menlo, monospace;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', system-ui, sans-serif;
box-sizing: border-box;
max-width: 800px;
margin: 0 auto;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-pytuple[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--error: #e57373;
--error-soft: #3a2222;
}
.infographic-pytuple *, .infographic-pytuple *::before, .infographic-pytuple *::after { box-sizing: border-box; }
.infographic-pytuple .pt-wrap { padding: 0 clamp(1rem, 4vw, 2rem) 1.5rem; }
.infographic-pytuple h1 {
font-family: var(--display-font); font-weight: 600;
font-size: clamp(1.55rem, 5vw, 2.1rem); text-align: center; margin: 1.5rem 0 0.25rem; letter-spacing: -0.01em;
}
.infographic-pytuple .pt-sub { text-align: center; color: var(--ink-soft); font-size: 0.88rem; margin: 0 0 1.4rem; }
.infographic-pytuple .pt-tabs { display: flex; justify-content: center; gap: 0.4rem; margin-bottom: 1.5rem; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.infographic-pytuple .pt-tab-btn {
font: inherit; font-family: var(--mono-font); font-size: 0.8rem; font-weight: 700;
background: none; border: none; border-bottom: 2.5px solid transparent; color: var(--ink-soft);
padding: 0.55rem 0.8rem; cursor: pointer; margin-bottom: -1px;
}
.infographic-pytuple .pt-tab-btn.is-active { color: var(--accent); border-bottom-color: var(--accent); }
.infographic-pytuple .pt-panel.is-hidden-tab { display: none; }
/* box visualization */
.infographic-pytuple .box-row { display: flex; justify-content: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.6rem; min-height: 70px; align-items: flex-end; }
.infographic-pytuple .box-col { display: flex; flex-direction: column; align-items: center; gap: 0.2rem; }
.infographic-pytuple .box-idx { font-family: var(--mono-font); font-size: 0.65rem; color: var(--ink-soft); background: none; border: none; padding: 0; }
.infographic-pytuple .box-idx.neg { color: var(--accent); cursor: pointer; }
.infographic-pytuple .box {
min-width: 56px; padding: 0 0.5rem; height: 44px; display: flex; align-items: center; justify-content: center;
font-family: var(--mono-font); font-size: 0.82rem; font-weight: 700;
background: var(--paper-alt); border: 1.5px solid var(--line); border-radius: 6px; color: var(--ink);
transition: background 0.2s, border-color 0.2s, transform 0.2s; cursor: default;
}
.infographic-pytuple .box.is-clickable { cursor: pointer; }
.infographic-pytuple .box.is-highlight { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); transform: translateY(-3px); }
.infographic-pytuple .box.is-locked { border-style: dashed; }
.infographic-pytuple .box.is-shake { animation: pt-shake 0.4s; border-color: var(--error); background: var(--error-soft); }
@keyframes pt-shake {
0%, 100% { transform: translateX(0); } 20% { transform: translateX(-4px); } 40% { transform: translateX(4px); }
60% { transform: translateX(-3px); } 80% { transform: translateX(3px); }
}
.infographic-pytuple .len-badge {
display: block; text-align: center; font-family: var(--mono-font); font-size: 0.75rem; color: var(--accent);
font-weight: 700; margin-bottom: 1.1rem;
}
.infographic-pytuple .lock-note {
text-align: center; font-size: 0.78rem; color: var(--ink-soft); margin: -0.5rem 0 1.1rem;
}
/* method cards (reused across tabs) */
.infographic-pytuple .method-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.6rem; margin-bottom: 1.1rem; }
@media (max-width: 560px) { .infographic-pytuple .method-grid { grid-template-columns: 1fr; } }
.infographic-pytuple .method-card { background: var(--paper-alt); border: 1px solid var(--line); border-radius: 6px; padding: 0.6rem 0.7rem; }
.infographic-pytuple .method-name { font-family: var(--mono-font); font-size: 0.8rem; font-weight: 700; color: var(--ink); margin-bottom: 0.4rem; }
.infographic-pytuple .method-row { display: flex; gap: 0.35rem; align-items: center; flex-wrap: wrap; }
.infographic-pytuple .method-row input {
font-family: var(--mono-font); font-size: 0.78rem; padding: 0.28rem 0.4rem;
border: 1px solid var(--line); border-radius: 4px; background: var(--paper); color: var(--ink); width: 72px;
}
.infographic-pytuple .method-row input:focus { outline: none; border-color: var(--accent); }
.infographic-pytuple .run-btn {
font: inherit; font-family: var(--mono-font); font-size: 0.75rem; font-weight: 700;
background: var(--accent); color: #fff; border: none; border-radius: 4px;
padding: 0.3rem 0.6rem; cursor: pointer;
}
.infographic-pytuple .run-btn.danger { background: var(--error); }
/* terminal log β always dark */
.infographic-pytuple .device {
--ed-bg: #1e1e1e; --ed-bar: #2d2d2d; --ed-text: #d4d4d4; --ed-soft: #8a8a8a; --ed-ok: #6fdc8c; --ed-err: #ff6b6b;
background: var(--ed-bg); border: 1px solid var(--line); border-radius: 8px; overflow: hidden;
}
.infographic-pytuple .device-bar {
display: flex; align-items: center; gap: 0.4rem;
background: var(--ed-bar); padding: 0.5rem 0.7rem; border-bottom: 1px solid #3a3a3a;
font-size: 0.72rem; color: var(--ed-soft); font-weight: 600;
}
.infographic-pytuple .device-bar .dot { width: 9px; height: 9px; border-radius: 50%; background: #5a5a5a; }
.infographic-pytuple .device-bar .dot:nth-child(1) { background: #ff5f56; }
.infographic-pytuple .device-body {
padding: 0.8rem 0.9rem; font-family: var(--mono-font); font-size: 0.78rem; color: var(--ed-text);
min-height: 50px; max-height: 170px; overflow-y: auto;
}
.infographic-pytuple .log-line { display: flex; gap: 0.5rem; line-height: 1.6; opacity: 0; animation: pt-fadein 0.25s ease forwards; flex-wrap: wrap; }
@keyframes pt-fadein { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: translateY(0); } }
.infographic-pytuple .log-line .p { color: var(--ed-ok); font-weight: 700; }
.infographic-pytuple .log-line .arrow { color: var(--ed-soft); }
.infographic-pytuple .log-line .res { color: #fff; }
.infographic-pytuple .log-line.err .res { color: var(--ed-err); }
.infographic-pytuple .log-empty { color: var(--ed-soft); }
/* single-element gotcha */
.infographic-pytuple .gotcha-row { display: flex; justify-content: center; gap: 0.5rem; margin: 1.2rem 0 0.6rem; }
.infographic-pytuple .gotcha-btn {
font: inherit; font-family: var(--mono-font); font-size: 0.85rem; font-weight: 700;
background: var(--paper-alt); border: 1.5px solid var(--line); color: var(--ink-soft);
padding: 0.45rem 0.9rem; cursor: pointer; border-radius: 5px;
}
.infographic-pytuple .gotcha-btn.is-selected { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.infographic-pytuple .gotcha-result {
text-align: center; font-family: var(--mono-font); font-size: 0.95rem; font-weight: 700; color: var(--accent); margin-bottom: 0.3rem;
}
.infographic-pytuple .pt-caption { text-align: center; font-size: 0.8rem; color: var(--ink-soft); margin-top: 0.3rem; }
/* indexing tab */
.infographic-pytuple .idx-picker-row {
display: flex; justify-content: center; align-items: center; gap: 0.35rem; margin-top: 0.9rem;
font-family: var(--mono-font); font-size: 0.95rem; color: var(--ink-soft);
}
.infographic-pytuple .idx-picker-input {
width: 60px; font-family: var(--mono-font); font-size: 0.95rem; font-weight: 700; text-align: center;
padding: 0.3rem 0.3rem; border: 1.5px solid var(--line); border-radius: 5px; background: var(--paper-alt); color: var(--accent);
}
.infographic-pytuple .idx-picker-input:focus { outline: none; border-color: var(--accent); }
.infographic-pytuple .idx-result {
text-align: center; font-family: var(--mono-font); font-size: 1rem; font-weight: 700; color: var(--accent);
margin: 0.8rem 0 1.2rem; min-height: 1.4em;
}
.infographic-pytuple .slice-controls { display: flex; justify-content: center; align-items: center; gap: 1.2rem; margin-bottom: 0.6rem; }
.infographic-pytuple .slice-slot { display: flex; flex-direction: column; align-items: center; gap: 0.3rem; }
.infographic-pytuple .slice-slot span { font-family: var(--mono-font); font-size: 0.7rem; color: var(--ink-soft); }
.infographic-pytuple .stepper { display: flex; align-items: center; gap: 0.4rem; }
.infographic-pytuple .stepper button {
width: 28px; height: 28px; border-radius: 50%; border: 1.5px solid var(--line);
background: var(--paper-alt); color: var(--ink); font-size: 1rem; font-weight: 700; cursor: pointer;
}
.infographic-pytuple .stepper .val { font-family: var(--display-font); font-size: 1.1rem; color: var(--accent); min-width: 1.6ch; text-align: center; }
/* unpacking tab */
.infographic-pytuple .unpack-inputs { display: flex; flex-direction: column; align-items: center; gap: 0.6rem; margin-bottom: 1rem; }
.infographic-pytuple .unpack-row { display: flex; align-items: center; gap: 0.5rem; }
.infographic-pytuple .unpack-row span { font-family: var(--mono-font); font-size: 0.8rem; color: var(--ink-soft); }
.infographic-pytuple .unpack-input {
font-family: var(--mono-font); font-size: 0.85rem; text-align: center;
padding: 0.4rem 0.6rem; border: 1.5px solid var(--line); background: var(--paper-alt); color: var(--ink);
border-radius: 5px; width: 260px;
}
.infographic-pytuple .unpack-input:focus { outline: none; border-color: var(--accent); }
.infographic-pytuple .unpack-diagram { display: flex; justify-content: center; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin: 1rem 0; }
.infographic-pytuple .arrow-down { text-align: center; color: var(--accent); font-size: 1.3rem; margin: 0.4rem 0; }
.infographic-pytuple .pill-row { display: flex; justify-content: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.8rem; }
.infographic-pytuple .var-pill {
font-family: var(--mono-font); font-size: 0.82rem; font-weight: 700; padding: 0.4rem 0.7rem;
border-radius: 6px; border: 1.5px solid var(--accent); background: var(--accent-soft); color: var(--accent);
}
.infographic-pytuple .var-pill.is-star { border-style: dashed; }
.infographic-pytuple .unpack-error {
text-align: center; font-family: var(--mono-font); font-size: 0.85rem; font-weight: 700; color: var(--error);
margin-bottom: 0.8rem;
}
@media (prefers-reduced-motion: reduce) {
.infographic-pytuple *, .infographic-pytuple *::before, .infographic-pytuple *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="pt-wrap">
<h1>Python Tuples</h1>
<p class="pt-sub">Ordered like a list. Locked like a vault.</p>
<div class="pt-tabs">
<button class="pt-tab-btn is-active" data-tab="lock">Immutability</button>
<button class="pt-tab-btn" data-tab="idx">Indexing & Slicing</button>
<button class="pt-tab-btn" data-tab="unpack">Packing & Unpacking</button>
</div>
<!-- IMMUTABILITY TAB -->
<div class="pt-panel" id="tabLock">
<div class="box-row" id="lockBoxRow"></div>
<span class="len-badge" id="lockLenBadge">len(point) = 3</span>
<p class="lock-note">point = (10, 20, 30) β same box, every time. Tuples can't change size or values.</p>
<div class="method-grid">
<div class="method-card">
<div class="method-name">point[i] = x</div>
<div class="method-row">
<input id="mutIdx" type="text" value="0" style="width:44px" />
<input id="mutVal" type="text" value="99" />
<button class="run-btn danger" data-method="mutate">Try it</button>
</div>
</div>
<div class="method-card">
<div class="method-name">.count(x)</div>
<div class="method-row">
<input id="countInput" type="text" value="20" />
<button class="run-btn" data-method="count">Run</button>
</div>
</div>
<div class="method-card">
<div class="method-name">.index(x)</div>
<div class="method-row">
<input id="indexInput" type="text" value="30" />
<button class="run-btn" data-method="index">Run</button>
</div>
</div>
<div class="method-card">
<div class="method-name">len(point)</div>
<div class="method-row"><button class="run-btn" data-method="len">Run</button></div>
</div>
</div>
<div class="device">
<div class="device-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span> History</div>
<div class="device-body" id="lockLog"><div class="log-empty">Try a method to see it hereβ¦</div></div>
</div>
<div class="gotcha-row">
<button class="gotcha-btn is-selected" data-form="paren">(5)</button>
<button class="gotcha-btn" data-form="tuple">(5,)</button>
</div>
<div class="gotcha-result" id="gotchaResult">type((5)) = <class 'int'></div>
<p class="pt-caption">Parentheses alone aren't a tuple β the trailing comma is what makes it one.</p>
</div>
<!-- INDEXING/SLICING TAB -->
<div class="pt-panel is-hidden-tab" id="tabIdx">
<div class="box-row" id="idxBoxRowPos"></div>
<div class="box-row" id="idxBoxRowNeg" style="margin-top:-0.4rem;"></div>
<span class="len-badge" id="idxLenBadge">len(point) = 3</span>
<p class="pt-caption">Tap a box (or its index) β positive above, negative below.</p>
<div class="idx-picker-row">
<span>point[</span>
<input class="idx-picker-input" id="idxPickerInput" type="text" value="0" inputmode="numeric" />
<span>]</span>
</div>
<div class="idx-result" id="idxSingleResult">point[0] = 10</div>
<div class="slice-controls">
<div class="slice-slot">
<span>start</span>
<div class="stepper">
<button id="sliceStartMinus">β</button>
<span class="val" id="sliceStartVal">0</span>
<button id="sliceStartPlus">+</button>
</div>
</div>
<div class="slice-slot">
<span>end</span>
<div class="stepper">
<button id="sliceEndMinus">β</button>
<span class="val" id="sliceEndVal">2</span>
<button id="sliceEndPlus">+</button>
</div>
</div>
</div>
<div class="idx-result" id="sliceResult">point[0:2]</div>
<p class="pt-caption">Slicing a tuple returns a new tuple β reading works exactly like a list.</p>
</div>
<!-- PACKING/UNPACKING TAB -->
<div class="pt-panel is-hidden-tab" id="tabUnpack">
<div class="unpack-inputs">
<div class="unpack-row">
<span>values</span>
<input class="unpack-input" id="unpackValues" type="text" value="10, 20, 30" />
</div>
<div class="unpack-row">
<span>names</span>
<input class="unpack-input" id="unpackNames" type="text" value="a, b, c" />
</div>
</div>
<p class="pt-caption">Try a starred name like <strong style="font-family:var(--mono-font)">*b</strong> to collect the leftover items.</p>
<div class="pill-row" id="valuesPillRow"></div>
<div class="arrow-down">β unpack β</div>
<div class="pill-row" id="namesPillRow"></div>
<div class="unpack-error" id="unpackError" style="display:none;"></div>
</div>
</div>
<script>
(function () {
var root = document.currentScript.closest('.infographic-pytuple')
|| document.querySelector('.infographic-pytuple');
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) root.setAttribute('data-theme', 'dark');
/* ---------------- tabs ---------------- */
var tabBtns = root.querySelectorAll('.pt-tab-btn');
var panels = {
lock: root.querySelector('#tabLock'),
idx: root.querySelector('#tabIdx'),
unpack: root.querySelector('#tabUnpack')
};
tabBtns.forEach(function (btn) {
btn.addEventListener('click', function () {
tabBtns.forEach(function (b) { b.classList.toggle('is-active', b === btn); });
var target = btn.dataset.tab;
Object.keys(panels).forEach(function (key) {
panels[key].classList.toggle('is-hidden-tab', key !== target);
});
if (target === 'idx') renderIdxTab();
});
});
/* ---------------- shared read-only tuple ---------------- */
var point = [10, 20, 30];
function pyRepr(arr) {
return '(' + arr.join(', ') + (arr.length === 1 ? ',' : '') + ')';
}
function renderBoxRow(container, arr, opts) {
opts = opts || {};
container.innerHTML = '';
arr.forEach(function (val, i) {
var col = document.createElement('div');
col.className = 'box-col';
if (opts.showPosIdx) {
var idxLbl = document.createElement('span');
idxLbl.className = 'box-idx';
idxLbl.textContent = i;
col.appendChild(idxLbl);
}
var box = document.createElement(opts.clickable ? 'button' : 'div');
box.className = 'box' + (opts.clickable ? ' is-clickable' : '') + (opts.locked ? ' is-locked' : '');
if (opts.highlightSet && opts.highlightSet.has(i)) box.classList.add('is-highlight');
box.textContent = val;
box.dataset.idx = i;
if (opts.onClick) box.addEventListener('click', function () { opts.onClick(i, box); });
col.appendChild(box);
container.appendChild(col);
});
}
/* ---------------- IMMUTABILITY TAB ---------------- */
var lockBoxRow = root.querySelector('#lockBoxRow');
var lockLenBadge = root.querySelector('#lockLenBadge');
var lockLog = root.querySelector('#lockLog');
var lockFirstLog = true;
function renderLock() {
renderBoxRow(lockBoxRow, point, { locked: true });
lockLenBadge.textContent = 'len(point) = ' + point.length;
}
function logLine(logEl, firstFlagName, code, result, isErr) {
var line = document.createElement('div');
line.className = 'log-line' + (isErr ? ' err' : '');
line.innerHTML = '<span class="p">>>></span><span>' + code + '</span>' +
(result !== undefined ? '<span class="arrow">β</span><span class="res">' + result + '</span>' : '');
logEl.appendChild(line);
logEl.scrollTop = logEl.scrollHeight;
}
root.querySelectorAll('#tabLock .run-btn').forEach(function (btn) {
btn.addEventListener('click', function () {
var method = btn.dataset.method;
if (lockFirstLog) { lockLog.innerHTML = ''; lockFirstLog = false; }
if (method === 'mutate') {
var i = parseInt(root.querySelector('#mutIdx').value, 10);
var v = root.querySelector('#mutVal').value.trim();
var code = 'point[' + i + '] = ' + v;
logLine(lockLog, null, code, "TypeError: 'tuple' object does not support item assignment", true);
var boxes = lockBoxRow.querySelectorAll('.box');
var target = boxes[i];
if (target) {
target.classList.remove('is-shake');
void target.offsetWidth;
target.classList.add('is-shake');
setTimeout(function () { target.classList.remove('is-shake'); }, 450);
}
} else if (method === 'count') {
var cv = root.querySelector('#countInput').value.trim();
var n = point.filter(function (x) { return String(x) === cv; }).length;
logLine(lockLog, null, 'point.count(' + cv + ')', n);
} else if (method === 'index') {
var iv = root.querySelector('#indexInput').value.trim();
var pos = point.findIndex(function (x) { return String(x) === iv; });
if (pos === -1) {
logLine(lockLog, null, 'point.index(' + iv + ')', 'ValueError: tuple.index(x): x not in tuple', true);
} else {
logLine(lockLog, null, 'point.index(' + iv + ')', pos);
}
} else if (method === 'len') {
logLine(lockLog, null, 'len(point)', point.length);
}
});
});
/* single-element gotcha */
var gotchaBtns = root.querySelectorAll('.gotcha-btn');
var gotchaResult = root.querySelector('#gotchaResult');
gotchaBtns.forEach(function (btn) {
btn.addEventListener('click', function () {
gotchaBtns.forEach(function (b) { b.classList.toggle('is-selected', b === btn); });
if (btn.dataset.form === 'paren') {
gotchaResult.textContent = "type((5)) = <class 'int'>";
} else {
gotchaResult.textContent = "type((5,)) = <class 'tuple'>";
}
});
});
/* ---------------- INDEXING / SLICING TAB ---------------- */
var idxBoxRowPos = root.querySelector('#idxBoxRowPos');
var idxBoxRowNeg = root.querySelector('#idxBoxRowNeg');
var idxLenBadge = root.querySelector('#idxLenBadge');
var idxPickerInput = root.querySelector('#idxPickerInput');
var idxSingleResult = root.querySelector('#idxSingleResult');
var sliceResult = root.querySelector('#sliceResult');
var sliceStartVal = root.querySelector('#sliceStartVal');
var sliceEndVal = root.querySelector('#sliceEndVal');
var sliceStart = 0;
var sliceEnd = 2;
function clamp(v, lo, hi) { return Math.max(lo, Math.min(hi, v)); }
function resolveIndex(raw) {
var n = point.length;
if (isNaN(raw)) return { ok: false, msg: 'enter a whole number' };
if (raw < -n || raw >= n) return { ok: false, msg: 'IndexError: tuple index out of range', pos: null };
var pos = raw < 0 ? raw + n : raw;
return { ok: true, pos: pos, value: point[pos] };
}
function renderIdxTab() {
sliceStart = clamp(sliceStart, -point.length, point.length);
sliceEnd = clamp(sliceEnd, -point.length, point.length);
var rawIdx = parseInt(idxPickerInput.value, 10);
var resolved = resolveIndex(rawIdx);
var hl = new Set();
var normStart = sliceStart < 0 ? sliceStart + point.length : sliceStart;
var normEnd = sliceEnd < 0 ? sliceEnd + point.length : sliceEnd;
for (var k = Math.max(0, normStart); k < Math.min(point.length, normEnd); k++) hl.add(k);
if (resolved.ok) hl.add(resolved.pos);
renderBoxRow(idxBoxRowPos, point, {
showPosIdx: true,
clickable: true,
highlightSet: hl,
onClick: function (i) {
idxPickerInput.value = i;
renderIdxTab();
}
});
idxBoxRowNeg.innerHTML = '';
point.forEach(function (v, i) {
var col = document.createElement('div');
col.className = 'box-col';
var lbl = document.createElement('button');
lbl.className = 'box-idx neg';
lbl.style.cssText = 'background:none;border:none;cursor:pointer;font-family:inherit;font-size:inherit;padding:0;';
lbl.textContent = i - point.length;
lbl.addEventListener('click', function () {
idxPickerInput.value = i - point.length;
renderIdxTab();
});
col.appendChild(lbl);
idxBoxRowNeg.appendChild(col);
});
idxLenBadge.textContent = 'len(point) = ' + point.length;
idxSingleResult.textContent = resolved.ok
? ('point[' + rawIdx + '] = ' + resolved.value)
: (isNaN(rawIdx) ? 'Enter a whole number.' : resolved.msg);
sliceStartVal.textContent = sliceStart;
sliceEndVal.textContent = sliceEnd;
var sliceArr = point.slice(normStart, normEnd);
sliceResult.textContent = 'point[' + sliceStart + ':' + sliceEnd + '] = ' + pyRepr(sliceArr);
}
idxPickerInput.addEventListener('input', renderIdxTab);
root.querySelector('#sliceStartMinus').addEventListener('click', function () { sliceStart = clamp(sliceStart - 1, -point.length, point.length); renderIdxTab(); });
root.querySelector('#sliceStartPlus').addEventListener('click', function () { sliceStart = clamp(sliceStart + 1, -point.length, point.length); renderIdxTab(); });
root.querySelector('#sliceEndMinus').addEventListener('click', function () { sliceEnd = clamp(sliceEnd - 1, -point.length, point.length); renderIdxTab(); });
root.querySelector('#sliceEndPlus').addEventListener('click', function () { sliceEnd = clamp(sliceEnd + 1, -point.length, point.length); renderIdxTab(); });
/* ---------------- PACKING / UNPACKING TAB ---------------- */
var unpackValuesInput = root.querySelector('#unpackValues');
var unpackNamesInput = root.querySelector('#unpackNames');
var valuesPillRow = root.querySelector('#valuesPillRow');
var namesPillRow = root.querySelector('#namesPillRow');
var unpackErrorEl = root.querySelector('#unpackError');
function parseCsv(raw) {
return raw.split(',').map(function (s) { return s.trim(); }).filter(function (s) { return s.length > 0; });
}
function renderUnpack() {
var values = parseCsv(unpackValuesInput.value);
var names = parseCsv(unpackNamesInput.value);
valuesPillRow.innerHTML = '';
values.forEach(function (v) {
var pill = document.createElement('span');
pill.className = 'var-pill';
pill.textContent = v;
valuesPillRow.appendChild(pill);
});
var starIdx = -1;
for (var i = 0; i < names.length; i++) {
if (names[i].charAt(0) === '*') { starIdx = i; break; }
}
namesPillRow.innerHTML = '';
unpackErrorEl.style.display = 'none';
if (starIdx === -1) {
if (values.length !== names.length) {
unpackErrorEl.style.display = 'block';
unpackErrorEl.textContent = values.length > names.length
? ('ValueError: too many values to unpack (expected ' + names.length + ')')
: ('ValueError: not enough values to unpack (expected ' + names.length + ', got ' + values.length + ')');
return;
}
names.forEach(function (n, i) {
var pill = document.createElement('span');
pill.className = 'var-pill';
pill.textContent = n + ' = ' + values[i];
namesPillRow.appendChild(pill);
});
} else {
var before = names.slice(0, starIdx);
var after = names.slice(starIdx + 1);
var minRequired = before.length + after.length;
if (values.length < minRequired) {
unpackErrorEl.style.display = 'block';
unpackErrorEl.textContent = 'ValueError: not enough values to unpack (expected at least ' + minRequired + ')';
return;
}
var beforeVals = values.slice(0, before.length);
var afterVals = after.length ? values.slice(values.length - after.length) : [];
var middleVals = values.slice(before.length, values.length - after.length);
var starName = names[starIdx].slice(1);
before.forEach(function (n, i) {
var pill = document.createElement('span');
pill.className = 'var-pill';
pill.textContent = n + ' = ' + beforeVals[i];
namesPillRow.appendChild(pill);
});
var starPill = document.createElement('span');
starPill.className = 'var-pill is-star';
starPill.textContent = starName + ' = [' + middleVals.join(', ') + ']';
namesPillRow.appendChild(starPill);
after.forEach(function (n, i) {
var pill = document.createElement('span');
pill.className = 'var-pill';
pill.textContent = n + ' = ' + afterVals[i];
namesPillRow.appendChild(pill);
});
}
}
unpackValuesInput.addEventListener('input', renderUnpack);
unpackNamesInput.addEventListener('input', renderUnpack);
renderLock();
renderIdxTab();
renderUnpack();
})();
</script>
</div>