Functions, *args, **kwargs
Theme
Palette
Download
Caption (tap to copy)
📖 Deep dive (full written explanation)
This cover frames the day not as three separate syntax tricks but as one idea with two extensions. A function is the base concept; *args and **kwargs are simply ways to make that function accept a variable number of inputs. The headline signals that the post decodes the shape before any of the later angles pile on motivation or mechanics.
Starting with the concept matters because *args and **kwargs are notorious for looking like arcane symbols. Most learners can copy the pattern but freeze the moment they need to adapt it. Establishing what each piece fundamentally is — a named box, a tuple of extras, a dict of extras — makes every later variation feel like the same idea rather than new magic.
The core definition reframes a function as a contract, not just a code-saving device. You declare inputs and a body once, hide the implementation behind a name, and the rest of your program interacts only with that name. This abstraction is the entire reason functions exist: callers care about what a function does, not how.
This framing sets up why *args and **kwargs are valuable later. If a function is a box you hand inputs to, then the natural next question is 'what if I don't know in advance how many inputs there are?' That question is exactly what the two star forms answer, so grounding the function concept first makes their purpose obvious rather than mysterious.
The parameters-versus-arguments distinction is small but eliminates a surprising amount of confusion. Parameters are the names the function declares in its def line — the empty slots. Arguments are the concrete values supplied at the call site that fill those slots. People use the words interchangeably, but keeping them separate makes the rest of the day precise.
This matters because *args and **kwargs live entirely in the space between these two sides. On the parameter side they declare 'I'll accept extras'; on the argument side the caller supplies those extras. Without a clean mental split between the declaration and the call, the packing-versus-unpacking distinction in the mechanics post becomes much harder to grasp.
This first code slide grounds the abstraction in the simplest possible function: add two numbers and return the result. The inline comments explicitly label a and b as parameters and 3 and 4 as arguments, reinforcing the distinction from the previous slide in concrete code.
The key observation is the clean separation between definition and use. The def line describes behavior once; the call invokes it with real values. Running this and then calling add with different arguments is the fastest way to feel that a function is a reusable template, not a one-shot block of code — the foundation everything else builds on.
This slide introduces *args as the first extension: a single star before a parameter name tells Python to collect every extra positional argument into a tuple. The crucial clarification is that 'args' is convention, not syntax — the star does the work, and you could name it anything. This preempts the misconception tackled in the final mistake slide.
Thinking of the star as a vacuum that soaks up leftover positional values is the mental image to keep. However many positional arguments the caller supplies beyond the named parameters, they all land in that one tuple. This is what makes a function variadic — able to accept any number of inputs — which is the capability the 'why' post builds its case around.
The code makes *args tangible by defining a total function that sums whatever it receives. Calling it with two arguments, then four, then none demonstrates the range: args is a tuple of whatever was passed, including the empty tuple when nothing is. The same function handles all three calls without modification.
The empty-call case is worth dwelling on. total() returns 0 because sum of an empty tuple is 0 — no special-casing required. Seeing that a variadic function gracefully handles zero arguments removes a common worry and shows why *args is the natural tool whenever the count of inputs genuinely varies from call to call.
This slide introduces **kwargs as the mirror of *args: two stars collect every extra keyword (named) argument into a dictionary. The symmetry is the point — positional extras flow to the *args tuple, named extras flow to the **kwargs dict. Once a learner sees these as a matched pair handling the two kinds of arguments, the whole system clicks.
The dict structure matters because it preserves the names the caller used. Inside the function, kwargs maps each keyword to its value, so you can look options up by name. This is precisely what makes **kwargs the backbone of flexible APIs and option-passing, a use the 'why' post develops in depth.
The code demonstrates **kwargs by iterating over the collected dictionary and printing each key-value pair. Calling show with name and age as keyword arguments produces a kwargs dict of {'name': 'Ada', 'age': 30}, which the loop then unpacks. Seeing the named arguments survive as dictionary keys makes the mechanism concrete.
The takeaway is that **kwargs gives a function open-ended named inputs without declaring each one. The function doesn't need to know in advance which keys it'll receive — it can inspect, forward, or selectively use them. That open-endedness is exactly what lets wrappers and configurable functions accept options they were never explicitly written to expect.
The flow diagram traces a single mixed call — f(1, 2, x=3, y=4) — through the routing process. Fixed parameters are matched first, then leftover positional values fall into *args as a tuple, and leftover named values fall into **kwargs as a dict. Visualizing all four destinations at once makes the routing rules concrete before the mechanics post formalizes them.
The value of seeing this as discrete stages is that it counters the tendency to view a function call as one opaque step. Each argument has a clear destination determined by whether it's positional or named and whether a fixed parameter claimed it first. That routing intuition is what the 'How It Works' post turns into a precise algorithm.
This slide drives home that in a def line the stars are a PACKING operation: they gather leftover arguments into a tuple and a dict. Repeating that args and kwargs are mere conventions — *nums and **opts work identically — reinforces the lesson that Python only counts the stars, not the names.
Flagging packing explicitly here plants a seed the mechanics post harvests: the same stars perform the opposite operation (unpacking) at a call site. Establishing 'in a def, stars pack' now means the later 'in a call, stars unpack' lands as a clean mirror rather than a contradiction. The star-count rule — one for positional, two for keyword — is the single most portable fact in the whole day.
The mental-model slide distills the entire concept into a memorizable checklist: a function is a named box, parameters are slots and arguments are values, one star packs positional extras into a tuple, two stars pack keyword extras into a dict, and the star count — not the name — is what matters.
These five bullets are designed to be the thing a reader recalls weeks later. Each maps to one of the building blocks introduced in the post, so running a confusing function signature against this list resolves most uncertainty. The deliberate emphasis on 'star count, not name' is what frees learners from treating args and kwargs as sacred words.
The closing mistake corrects the single most common beginner misconception: that 'args' and 'kwargs' are reserved keywords with special meaning. They are ordinary variable names chosen by convention. Demonstrating that *things and **opts behave identically removes the false sense that there's hidden machinery tied to those specific words.
Getting this straight early prevents a cascade of confusion in the later posts. Once a learner accepts that Python cares only about the one or two stars, every subsequent example — wrappers, forwarding, keyword-only arguments — reads as variations on a simple, consistent rule rather than a collection of special cases to memorize.
This CTA closes the concept post and points to the payoff. Having established what functions, *args, and **kwargs are, the natural next question is why this flexibility is worth having — which is exactly what Day 18's second angle tackles.
The teaser frames it as the difference between a rigid function and one that scales, setting up the 'Why It Matters' post's argument that *args and **kwargs are what let functions bend instead of break as requirements grow.