π Callback Functions
A callback function is a function that is passed to another function as an argument and is called later by that function.
Callbacks are commonly used with higher-order functions.
πΉ Basic Example
def greet():
print("Hello!")
def execute(callback):
callback()
execute(greet) #Hello!Here:
greet β Callback function π
execute() β Receives and calls the callbackπΉ Callback with Arguments
def greet(name):
print("Hello", name)
def execute(callback):
callback("Codeveda")
execute(greet) #Hello CodevedaThe execute() function decides when and how to call greet().
β‘ Callback with Lambda
A lambda can also be used as a callback:
def execute(callback):
print(callback(10))
execute(lambda x: x * 2) #20Here, the lambda function is passed as the callback.
π Callback vs Higher-Order Function
These concepts are closely related:
Higher-Order Function
β
Accepts a function
β
That function can act as a CallbackExample:
def double(x):
return x * 2
def process(callback, value):
return callback(value)
print(process(double, 5)) #10Here:
doubleβ Callback function πprocessβ Higher-order function π
<div class="infographic-pycallback2">
<style>
.infographic-pycallback2 {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--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: 620px;
margin: 0 auto;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-pycallback2[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.infographic-pycallback2 *, .infographic-pycallback2 *::before, .infographic-pycallback2 *::after { box-sizing: border-box; }
.infographic-pycallback2 .cb-wrap { padding: 0 clamp(1rem, 4vw, 2rem) 1.5rem; }
.infographic-pycallback2 h1 {
font-family: var(--display-font); font-weight: 600;
font-size: clamp(1.5rem, 5vw, 2.05rem); text-align: center; margin: 1.5rem 0 0.25rem; letter-spacing: -0.01em;
}
.infographic-pycallback2 .cb-sub { text-align: center; color: var(--ink-soft); font-size: 0.86rem; margin: 0 0 1.4rem; }
.infographic-pycallback2 .code-line {
font-family: var(--mono-font); font-size: 0.85rem; text-align: center; color: var(--ink);
background: var(--paper-alt); border: 1px solid var(--line); border-radius: 8px;
padding: 0.7rem 0.9rem; margin-bottom: 1.2rem; line-height: 1.8;
}
.infographic-pycallback2 .code-line .fn { color: var(--accent); font-weight: 700; }
.infographic-pycallback2 .ctl-row { display: flex; justify-content: center; gap: 0.5rem; margin-bottom: 1rem; flex-wrap: wrap; align-items: center; }
.infographic-pycallback2 .ctl-row input {
font-family: var(--mono-font); font-size: 0.85rem; padding: 0.4rem 0.6rem;
border: 1.5px solid var(--line); border-radius: 5px; background: var(--paper-alt); color: var(--ink); width: 100px;
text-align: center;
}
.infographic-pycallback2 .ctl-row input:focus { outline: none; border-color: var(--accent); }
.infographic-pycallback2 .chip-btn {
font: inherit; font-family: var(--mono-font); font-size: 0.8rem; font-weight: 700;
background: var(--paper-alt); border: 1.5px solid var(--line); color: var(--ink-soft);
padding: 0.42rem 0.75rem; cursor: pointer; border-radius: 6px;
}
.infographic-pycallback2 .chip-btn.is-selected { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.infographic-pycallback2 .run-row { display: flex; justify-content: center; margin-bottom: 0.9rem; }
.infographic-pycallback2 .run-btn {
font: inherit; font-family: var(--mono-font); font-size: 0.85rem; font-weight: 700;
background: var(--accent); color: #fff; border: none; border-radius: 999px;
padding: 0.55rem 1.2rem; cursor: pointer;
}
.infographic-pycallback2 .run-btn:disabled { opacity: 0.5; cursor: default; }
.infographic-pycallback2 .flow-row { display: flex; align-items: center; justify-content: center; gap: 0.7rem; margin-bottom: 1rem; flex-wrap: wrap; }
.infographic-pycallback2 .flow-box {
font-family: var(--mono-font); font-size: 0.85rem; font-weight: 700; text-align: center;
padding: 0.6rem 0.9rem; border-radius: 8px; border: 2px solid var(--line); background: var(--paper-alt); color: var(--ink-soft);
transition: border-color 0.25s, background 0.25s, color 0.25s;
min-width: 110px;
}
.infographic-pycallback2 .flow-box.is-active { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.infographic-pycallback2 .flow-arrow { color: var(--ink-soft); font-size: 1.2rem; }
.infographic-pycallback2 .device {
--ed-bg: #1e1e1e; --ed-bar: #2d2d2d; --ed-text: #d4d4d4; --ed-soft: #8a8a8a; --ed-ok: #6fdc8c;
background: var(--ed-bg); border: 1px solid var(--line); border-radius: 8px; overflow: hidden;
}
.infographic-pycallback2 .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-pycallback2 .device-bar .dot { width: 9px; height: 9px; border-radius: 50%; background: #5a5a5a; }
.infographic-pycallback2 .device-bar .dot:nth-child(1) { background: #ff5f56; }
.infographic-pycallback2 .device-body { padding: 0.8rem 0.9rem; font-family: var(--mono-font); font-size: 0.85rem; color: var(--ed-text); min-height: 50px; }
.infographic-pycallback2 .log-line { display: flex; gap: 0.5rem; opacity: 0; animation: cb2-fadein 0.25s ease forwards; }
@keyframes cb2-fadein { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: translateY(0); } }
.infographic-pycallback2 .log-line .p { color: var(--ed-ok); font-weight: 700; }
.infographic-pycallback2 .log-line .out { color: #fff; font-weight: 600; }
.infographic-pycallback2 .log-empty { color: var(--ed-soft); }
.infographic-pycallback2 .cb-caption { text-align: center; font-size: 0.85rem; color: var(--ink-soft); margin-top: 0.9rem; }
@media (prefers-reduced-motion: reduce) {
.infographic-pycallback2 *, .infographic-pycallback2 *::before, .infographic-pycallback2 *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="cb-wrap">
<h1>Callbacks</h1>
<p class="cb-sub">A function you hand to another function, to be called later.</p>
<div class="code-line">
<span class="fn">def</span> greet(name, callback):<br>
message = f"Hello, {name}!"<br>
callback(message)<br>
<br>
<span class="fn">def</span> print_it(msg): print(msg)<br>
<span class="fn">def</span> shout_it(msg): print(msg.upper())
</div>
<div class="ctl-row">
<input id="nameInput" type="text" value="Alice" />
<button class="chip-btn is-selected" data-cb="print_it">print_it</button>
<button class="chip-btn" data-cb="shout_it">shout_it</button>
</div>
<div class="run-row">
<button class="run-btn" id="runBtn">Run: greet("Alice", print_it)</button>
</div>
<div class="flow-row">
<div class="flow-box" id="boxGreet">greet()</div>
<span class="flow-arrow">β</span>
<div class="flow-box" id="boxCallback">callback(message)</div>
</div>
<div class="device">
<div class="device-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span> Terminal</div>
<div class="device-body" id="cbLog"><div class="log-empty">greet() builds the message, then hands it to whichever callback you passed in.</div></div>
</div>
<p class="cb-caption">greet() doesn't know or care what callback does β it just calls it when it's ready.</p>
</div>
<script>
(function () {
var root = document.currentScript.closest('.infographic-pycallback2')
|| document.querySelector('.infographic-pycallback2');
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');
var nameInput = root.querySelector('#nameInput');
var cbBtns = root.querySelectorAll('.chip-btn');
var runBtn = root.querySelector('#runBtn');
var boxGreet = root.querySelector('#boxGreet');
var boxCallback = root.querySelector('#boxCallback');
var cbLog = root.querySelector('#cbLog');
var currentCb = 'print_it';
var firstLog = true;
function updateRunBtn() {
runBtn.textContent = 'Run: greet("' + (nameInput.value || '') + '", ' + currentCb + ')';
}
nameInput.addEventListener('input', updateRunBtn);
cbBtns.forEach(function (btn) {
btn.addEventListener('click', function () {
cbBtns.forEach(function (b) { b.classList.remove('is-selected'); });
btn.classList.add('is-selected');
currentCb = btn.dataset.cb;
updateRunBtn();
});
});
updateRunBtn();
function logLine(text) {
if (firstLog) { cbLog.innerHTML = ''; firstLog = false; }
var line = document.createElement('div');
line.className = 'log-line';
line.innerHTML = '<span class="p">>>></span><span class="out">' + text + '</span>';
cbLog.appendChild(line);
cbLog.scrollTop = cbLog.scrollHeight;
}
runBtn.addEventListener('click', function () {
var name = nameInput.value || '';
var message = 'Hello, ' + name + '!';
runBtn.disabled = true;
boxGreet.classList.add('is-active');
boxCallback.classList.remove('is-active');
setTimeout(function () {
boxGreet.classList.remove('is-active');
boxCallback.classList.add('is-active');
var out = currentCb === 'print_it' ? message : message.toUpperCase();
logLine(currentCb + '(message) β "' + out + '"');
runBtn.disabled = false;
setTimeout(function () { boxCallback.classList.remove('is-active'); }, 500);
}, 500);
});
})();
</script>
</div>