1️⃣ Why *args and **kwargs exist
Problem:
Normally a Python function expects a fixed number of arguments.
Solution:
*argsArguments- Collects extra positional arguments
- Store as touple
**kwargsKeyword Arguments- Collects extra keyword arguments
- Store as dictionary
- positional → *args → keyword → **kwargs
- ex. def func(a, b, *args, c=10, d=20, **kwargs):
2️⃣ *args (positional arguments)
def show(*args):
print(type(args)) # <class 'tuple'>
print(args) # (1, 2, 3)
show(1, 2, 3)
### 🔹 Mixing normal args and `*args`
def demo(a, b, *args):
print(a) # 1
print(b) # 2
print(args) # (3, 4, 5)
demo(1, 2, 3, 4, 5)3️⃣ **kwargs (keyword arguments)
def show(**kwargs):
print(type(kwargs)) # <class 'dict'>
print(kwargs)
show(a=1, b=2) # {'a': 1, 'b': 2}
# positional → *args → keyword → **kwargs
def mix(a, b, *args, x = None , **kwargs):
print(a, b) # 1 2
print(args) # (3, 4)
print(x) # 20
print(kwargs) # {'x': 10, 'y': 20}
mix(1, 2, 3, 4, x=10, y=20, z=30)4️⃣ Unpacking arguments
Function Call Unpacking
| Data | Call | Result |
|---|---|---|
extras = (1,2,3) | func(*extras) | same as func(1,2,3) |
info = {'a':1,'b':2} | func(**info) | same as func(a=1,b=2) |
# Unpacking list/tuple using
nums = [1, 2, 3]
print(*nums) # 1 2 3
# Unpacking dict
def show(a, b):
print(a, b) # 1 2
data = {"a": 1, "b": 2}
show(**data)
# Forwarding arguments (very important)
# Used heavily in decorators, wrappers, frameworks.
def wrapper(*args, **kwargs):
return original(*args, **kwargs)