Function Arguments — Positional, Keyword, Default, Variable (Layered)
2140 words
11 min read
Visual companion
Python
Type and operator map
Python Week 1: the first filter for runtime behavior
View
Revision summary
What this note is really saying
Short form
# Function Arguments — Positional, Keyword, Default, and Variable Parameter Binding > [!SUMMARY] > **Sitting Scope:** 45–60 minutes. Complete mental model of argument binding, parameter order invariants, mutable default traps, exam pattern taxonomy, and interactive attempt-first drills.

Function Arguments — Positional, Keyword, Default, and Variable Parameter Binding
Summary
Sitting Scope: 45–60 minutes. Complete mental model of argument binding, parameter order invariants, mutable default traps, exam pattern taxonomy, and interactive attempt-first drills.
1. Orientation & Where It Sits
In procedural Python, defining a function creates a callable object in memory. However, the mechanism by which Python maps arguments passed at a call site to parameters declared in a function signature is governed by a strict, unambiguous binding grammar. Mastering this grammar is the line between guessing how code executes and knowing exactly what the interpreter does before it runs.
[Basic Functions & Return] (Week 7) ──┐ ├──► [Function Arguments & Scope] (Week 8) ──► [Decorators & Functional Python] (Week 11) [Lists, Tuples & Dicts] (Weeks 5-6) ┘ └──► [OPPE Coding & Python Mocks] (Exam Desk)
- Prerequisites:
- Functions — Defining and Using —
defstatement, invocation, andreturnsemantics. - Lists & Dictionaries — Sequences, key-value mappings, and mutability.
- Functions — Defining and Using —
- Downstream Unlocks:
- Recursion with Accumulators (
798 - Recursion.md) — Passing default states across stack frames. - Higher-Order Functions & Decorators — Taking
*args, **kwargsto wrap arbitrary callables.
- Recursion with Accumulators (
2. Notation, Vocabulary & Etymology
| Term | Syntax / Notation | Semantic Meaning | Memory Hook |
|---|---|---|---|
| Parameter | def f(x, y): | The named variables declared in a function definition header. | The parking spot reserved in the function's blueprint. |
| Argument | f(10, 20) | The actual concrete values or objects passed into the function at call time. | The actual car parked in the spot. |
| Positional Argument | f(a, b) | An argument bound to a parameter strictly by its sequential order (left-to-right). | First-come, first-seated in a movie theatre row. |
| Keyword Argument | f(name="Ada") | An argument bound explicitly to a parameter by name, regardless of position. | A reserved seat with your name printed on the headrest. |
| Default Parameter | def f(mode="fast"): | A fallback value assigned to a parameter if the caller provides no argument. | A factory pre-set on a thermostat. |
*args (Var-Positional) | *args | Syntax packing zero or more positional arguments into a single tuple. | An accordion: expands to absorb any number of loose items into a box. |
**kwargs (Var-Keyword) | **kwargs | Syntax packing zero or more keyword arguments into a single dictionary. | A labelled filing box: absorbs any name-value pairs into a map. |
| Unpacking Operator | f(*L) or f(**D) | Expanding an iterable into positional args, or a dict into keyword args at call site. | Emptying a backpack onto the desk so items sit individually. |
3. Layered Conceptual Depth
Layer 1: The Intuition — The Custom Sandwich Order
Think of placing an order at a sandwich counter:
- Positional Parameters: The bread and the base protein must come first in exact sequence:
order("sourdough", "tofu"). - Default Parameters: Condiments come pre-selected unless you specify otherwise:
sauce="mayo",toasted=True. *args(Extra Toppings): You can request arbitrary loose toppings without defining individual slots:"olives", "pickles", "jalapenos"are bundled together into a basket.**kwargs(Custom Prep Instructions): You can pass arbitrary name-value preferences:cut="diagonal", wrap="foil", salt="extra"are collected onto a labelled order slip.
Layer 2: The Invariant Ordering Grammar
Python enforces a single non-negotiable ordering in both function definitions and function calls.
Signature Definition Grammar
Every function header must follow this exact sequential hierarchy:
def func(pos_only, /, standard_pos_or_kw, default_pos_or_kw=val, *args, kw_only, kw_only_default=val, **kwargs):
[1. Positional-Only] ──► [2. Pos-or-Keyword] ──► [3. Defaults] ──► [4. *args] ──► [5. Keyword-Only] ──► [6. **kwargs] (before '/') (after '*')
Important
The Golden Call-Site Rule:
In any function call, all positional arguments must precede keyword arguments.
Writing
func(a=1, 2) causes an immediate SyntaxError: positional argument follows keyword argument before execution even begins.Layer 3: Execution Mechanics — The Mutable Default Argument Trap
Why is the following code considered one of Python's most notorious exam traps?
pythondef append_element(val, target_list=[]): target_list.append(val) return target_list print(append_element(1)) # Output: [1] print(append_element(2)) # Output: [1, 2] <-- NOT [2]! print(append_element(3)) # Output: [1, 2, 3]
The Underlying Interpreter Architecture
- Definition Time vs Call Time:
Python executes
defstatements once when the module or script is loaded, NOT each time the function is called. - Object Creation:
When the interpreter encounters
target_list=[], it allocates a single list object in memory (e.g. at address0x7f80) and binds it to the function's__defaults__tuple. - Shared Persistence:
Every subsequent call to
append_element()that omits the second argument bindstarget_listto that exact same list in memory. Modifyingtarget_listmutates the permanent default object stored on the function object itself!
Function Object `append_element` ├── __code__: <bytecode> └── __defaults__: ([ 1, 2, 3 ],) <── Persistent list mutated across calls!
The Idiomatic Safe Pattern (Sentinel None)
pythondef append_element_safe(val, target_list=None): if target_list is None: target_list = [] # Creates a fresh list on EACH call target_list.append(val) return target_list
4. Worked Anatomy: Complex Binding Trace
Let us dissect a mixed signature call step-by-step:
Function Definition
pythondef calculate(base, multiplier=2, *deltas, scale=1, **flags): total = base * multiplier for d in deltas: total += d total *= scale if flags.get("round_result"): total = round(total) return total
Call Site
pythonresult = calculate(10, 3, 4, 6, scale=0.5, round_result=True)
Step-by-Step Binding Process
| Step | Formal Parameter | Argument Supplied | Bound Value | Type | Justification |
|---|---|---|---|---|---|
| 1 | base | 10 (1st positional) | 10 | int | Bound to 1st positional slot. |
| 2 | multiplier | 3 (2nd positional) | 3 | int | Overrides default value of 2. |
| 3 | *deltas | 4, 6 (remaining pos) | (4, 6) | tuple | Remaining positional args packed into a tuple. |
| 4 | scale | scale=0.5 (kwarg) | 0.5 | float | Explicit keyword-only match. |
| 5 | **flags | round_result=True | {"round_result": True} | dict | Extra keyword arguments packed into dict. |
Computation
total = 10 * 3 = 30- Iterating
deltas:total += 4(34),total += 6(40) - Scaling:
total = 40 * 0.5 = 20.0 - Flag check:
flags.get("round_result")isTrue→round(20.0) = 20 - Returns
20.
5. Non-Examples & The 3 Critical Failure Modes
┌── 1. SyntaxError: Positional Argument Follows Keyword Argument │ Signature Violations ────┼── 2. TypeError: Function Got Multiple Values for Argument │ └── 3. TypeError: Missing Required Keyword-Only Argument
1. Positional After Keyword
pythondef greet(first, last): return f"{first} {last}" greet(first="Grace", "Hopper") # SyntaxError: positional argument follows keyword argument
Python syntax prohibits bare positional values once keyword syntax has begun. You cannot switch back to positional notation within the same call.
2. Multiple Values for the Same Argument
pythondef process(x, y=10): return x + y process(5, 20, x=50) # TypeError: process() got multiple values for argument 'x'
Why it fails: The positional argument
5 already bound parameter x. Supplying x=50 attempts to re-bind x, which is illegal.3. Keyword-Only Argument Omission
pythondef configure(*, timeout=30, retries): pass configure(5) # TypeError: configure() takes 0 positional arguments but 1 was given configure(retries=3) # Correct!
Why it fails: Parameters listed after a bare
* or *args are strictly keyword-only. They can never receive values positionally.6. Question-Pattern Anatomy (8 Exam Reflexes)
In IITM BS DS Python exams (Quiz 2, Quiz 3, and OPPE), function argument questions follow eight standardized patterns:
| # | Pattern Name | Recognition Cue | Standard Attack Sequence | The Planted Trap |
|---|---|---|---|---|
| P1 | Mutable Default State Leak | def f(x, L=[]): called multiple times | Track L across calls as a shared, mutating reference | Assuming L resets to [] on every call |
| P2 | Positional-Keyword Collision | Positional argument followed by keyword matching 1st parameter | Check if the keyword name duplicates a slot already filled positionally | Assuming keyword overrides positional silently |
| P3 | Keyword-Only Bare Asterisk | Signature contains bare def f(a, *, b): | Verify that parameter b is passed strictly with b=val | Answering with positional evaluation |
| P4 | *args Tuple Immutability | Code attempts args[0] = x inside function | Recognize that args is packed as a tuple, not a list | Overlooking TypeError: 'tuple' object does not support item assignment |
| P5 | Call-Site Unpacking (* and **) | f(*tuple) or f(**dict) | Expand elements into respective positions/keys before binding | Treating the container as a single composite argument |
| P6 | Dictionary Key Type Requirement | f(**{1: "a", 2: "b"}) | Keys unpacked with ** must be strings matching parameter names | Expecting numeric keys to work as kwargs |
| P7 | Variable Args Absorbing Defaults | def f(a, b=2, *args) called with f(1, 2, 3) | 2nd positional binds b; remaining args go to args | Believing 3 binds to b and args remains empty |
| P8 | Passing None vs Omitting | def f(x=5): called as f(None) | None is an explicit argument; it overrides the default 5 | Assuming None defaults back to 5 |
7. Interactive Attempt-First Checks
Test your prediction reflexes. Write down your predicted output before opening the solutions.
1
Question 1
Type: MCQ | Marks: 1 | Topic: Persistent Mutable Defaults
What will be printed by the following Python program?
pythondef collect(item, box=[]): box.append(item) return len(box) a = collect("pencil") b = collect("eraser") c = collect("ruler", ["notebook"]) d = collect("pen") print(f"{a}-{b}-{c}-{d}")
MCQ
Persistent Mutable Defaults
3 Unit Assessment
A
1-1-2-1B
1-2-2-3C
1-2-1-3D
1-2-2-12
Question 2
Type: NAT | Marks: 1 | Topic: Argument Unpacking & Keyword-Only Calculation
What is the integer value printed by the following code?
pythondef score(mult, *vals, offset=10): return sum(vals) * mult + offset data = [2, 3, 5] ans = score(3, *data, 10, offset=5) print(ans)
NAT
3 Unit Assessment
3
Question 3
Type: MCQ | Marks: 1 | Topic: Call-site Grammar Violations
Which of the following function calls will raise a SyntaxError before the code runs?
pythondef register(id_num, name, role="Student", *courses, notify=True): pass
MCQ
Call-site Grammar Violations
3 Unit Assessment
A
register(101, "Aarav", "Tutor", "CS101", notify=False)B
register(101, name="Aarav", role="Admin")C
register(101, name="Aarav", "CS101")D
register(101, "Aarav", notify=True)Blank-Page Active Recall Challenge
Close this document. Take a blank paper and write:
- The general signature rule showing the relative positions of
pos,*args,kw_only, and**kwargs. - Explain why
def add(x, L=[]):behaves differently thandef add(x, L=None):when called multiple times.
8. Next Action & Spacing Protocol
- Immediate Next Chapter: Week 8: Recursion in Python — Combine parameter passing with recursive call stacks.
- Active Drill Desk: Visit the Quiz 3 Checkpoint Desk to drill Python predict-the-output questions.
- Spaced Review Suggestion: Re-attempt the Mutable Default trace (Question 1) in 48 hours to confirm persistent memory reflexes.
Provenance: Authored from scratch adhering to the Learning OS Authoring Cookbook standard (
docs/authoring/AUTHORING_COOKBOOK.md). Original imported reference 797 - Function Arguments — Positional, Keyword, Default, Variable.md preserved intact.