- Always place parameters with defaults after those without.
- Use
- Keyword arguments can be mixed with positional but must come after all positional arguments in the call.
- Defaults are evaluated once at definition time, not at each call.
- Use
None as a sentinel for mutable default values. - Keyword arguments can be mixed with positional but must come after all positional arguments in the call.
- Defaults are evaluated once at definition time, not at each call.
Which statement about default argument values in Python is true?
Anonymous Quiz
100%
They are evaluated each time the function is called
0%
They are evaluated once when the function is defined
0%
They can only be immutable objects
0%
They must be literals
📘 **Day 19: *args and **kwargs**
When you define a Python function, you usually list every parameter it expects:
```python
def greet(name, age):
print(f"Hello {name}, you are {age} years old.")
```
But real‑world functions often need **flexibility** – they may receive an unknown number of values or a set of named options that can change from call to call. That’s where `*args` and `**kwargs` come in.
**What `*args` does**
- The asterisk (`*`) before a parameter name tells Python *“collect any extra *positional* arguments into a tuple”*.
- Inside the function, `args` behaves exactly like any other tuple: you can iterate, index, or unpack it.
**What `**kwargs` does**
- The double asterisk (`**`) before a parameter name tells Python *“collect any extra *keyword* arguments into a dictionary”*.
- Inside the function, `kwargs` works like any dict: you can query keys, iterate over items, or use `.get()`.
**Why it works**
When a function call is evaluated, Python separates arguments into three groups:
1. **Positional arguments** that match the function’s regular parameters.
2. **Extra positional arguments** that don’t have a matching parameter – they go into `*args`.
3. **Keyword arguments** that match named parameters, plus any additional named arguments – the extras go into `**kwargs`.
Python builds `args` as a **tuple** because the order of positional arguments matters and they are immutable. It builds `kwargs` as a **dict** because each keyword must be unique and you need fast lookup by name.
**Calling a function with `*` and `**`**
The same symbols can be used *in reverse* when you **unpack** a sequence or mapping into a function call:
```python
values = (1, 2, 3)
options = {"verbose": True, "mode": "fast"}
def demo(a, b, c, verbose=False, mode="normal"):
print(a, b, c, verbose, mode)
demo(*values, **options) # expands to demo(1, 2, 3, verbose=True, mode="fast")
```
**Ordering rules**
When you mix regular parameters, `*args`, and `**kwargs` in a definition, the order must be:
```
def func(pos1, pos2, *args, kw1=None, kw2=None, **kwargs):
...
```
- Positional‑only (if using `/`), then normal positional, then `*args`, then keyword‑only, then `**kwargs`.
---
**Complete runnable example**
```python
def summarize(*numbers, **options):
"""
Prints a summary of any numeric values passed in,
and shows optional settings provided as keywords.
"""
# 1️⃣ *numbers is a tuple of all extra positional arguments
total = sum(numbers)
count = len(numbers)
# 2️⃣ **options is a dict of all extra keyword arguments
prefix = options.get("prefix", "Result")
show_average = options.get("average", False)
print(f"{prefix}:")
print(f" Count = {count}")
print(f" Sum = {total}")
if show_average and count > 0:
print(f" Avg = {total / count}")
# Calling with various combos
summarize(4, 7, 1, 3, prefix="Stats", average=True)
summarize(10, 20) # no extra keywords
summarize() # no numbers at all
```
**Walk‑through**
1. `def summarize(*numbers, **options):` –
- `*numbers` gathers **any number** of positional arguments into a tuple called `numbers`.
- `**options` gathers **any number** of keyword arguments into a dict called `options`.
2. Inside the function:
- `total = sum(numbers)` uses the built‑in `sum` on the tuple – works because tuples are iterable.
- `count = len(numbers)` gives how many numbers were passed.
- `options.get("prefix", "Result")` fetches the value for key `"prefix"` if present; otherwise defaults to `"Result"`.
- `options.get("average", False)` decides whether to display the average.
(continued below 👇)
When you define a Python function, you usually list every parameter it expects:
```python
def greet(name, age):
print(f"Hello {name}, you are {age} years old.")
```
But real‑world functions often need **flexibility** – they may receive an unknown number of values or a set of named options that can change from call to call. That’s where `*args` and `**kwargs` come in.
**What `*args` does**
- The asterisk (`*`) before a parameter name tells Python *“collect any extra *positional* arguments into a tuple”*.
- Inside the function, `args` behaves exactly like any other tuple: you can iterate, index, or unpack it.
**What `**kwargs` does**
- The double asterisk (`**`) before a parameter name tells Python *“collect any extra *keyword* arguments into a dictionary”*.
- Inside the function, `kwargs` works like any dict: you can query keys, iterate over items, or use `.get()`.
**Why it works**
When a function call is evaluated, Python separates arguments into three groups:
1. **Positional arguments** that match the function’s regular parameters.
2. **Extra positional arguments** that don’t have a matching parameter – they go into `*args`.
3. **Keyword arguments** that match named parameters, plus any additional named arguments – the extras go into `**kwargs`.
Python builds `args` as a **tuple** because the order of positional arguments matters and they are immutable. It builds `kwargs` as a **dict** because each keyword must be unique and you need fast lookup by name.
**Calling a function with `*` and `**`**
The same symbols can be used *in reverse* when you **unpack** a sequence or mapping into a function call:
```python
values = (1, 2, 3)
options = {"verbose": True, "mode": "fast"}
def demo(a, b, c, verbose=False, mode="normal"):
print(a, b, c, verbose, mode)
demo(*values, **options) # expands to demo(1, 2, 3, verbose=True, mode="fast")
```
**Ordering rules**
When you mix regular parameters, `*args`, and `**kwargs` in a definition, the order must be:
```
def func(pos1, pos2, *args, kw1=None, kw2=None, **kwargs):
...
```
- Positional‑only (if using `/`), then normal positional, then `*args`, then keyword‑only, then `**kwargs`.
---
**Complete runnable example**
```python
def summarize(*numbers, **options):
"""
Prints a summary of any numeric values passed in,
and shows optional settings provided as keywords.
"""
# 1️⃣ *numbers is a tuple of all extra positional arguments
total = sum(numbers)
count = len(numbers)
# 2️⃣ **options is a dict of all extra keyword arguments
prefix = options.get("prefix", "Result")
show_average = options.get("average", False)
print(f"{prefix}:")
print(f" Count = {count}")
print(f" Sum = {total}")
if show_average and count > 0:
print(f" Avg = {total / count}")
# Calling with various combos
summarize(4, 7, 1, 3, prefix="Stats", average=True)
summarize(10, 20) # no extra keywords
summarize() # no numbers at all
```
**Walk‑through**
1. `def summarize(*numbers, **options):` –
- `*numbers` gathers **any number** of positional arguments into a tuple called `numbers`.
- `**options` gathers **any number** of keyword arguments into a dict called `options`.
2. Inside the function:
- `total = sum(numbers)` uses the built‑in `sum` on the tuple – works because tuples are iterable.
- `count = len(numbers)` gives how many numbers were passed.
- `options.get("prefix", "Result")` fetches the value for key `"prefix"` if present; otherwise defaults to `"Result"`.
- `options.get("average", False)` decides whether to display the average.
(continued below 👇)
3. The three calls demonstrate flexibility:
- The first call passes four numbers and two keywords (
- The second call passes only numbers, relying on default keyword values.
- The third call passes nothing;
Key take‑aways
-
-
- The same
- Using these constructs lets you write highly reusable and extensible functions without fixing the exact number or names of arguments up front.
- The first call passes four numbers and two keywords (
prefix and average). - The second call passes only numbers, relying on default keyword values.
- The third call passes nothing;
numbers becomes an empty tuple, options an empty dict, and the function still runs safely.Key take‑aways
-
*args packs extra positional arguments into a tuple. -
**kwargs packs extra keyword arguments into a dictionary. - The same
* and ** symbols unpack a sequence or mapping when calling a function. - Using these constructs lets you write highly reusable and extensible functions without fixing the exact number or names of arguments up front.
What type does Python store extra positional arguments in when using *args?
Anonymous Quiz
0%
list
100%
tuple
0%
set
0%
dict