🕯️ Magic Note
Python’s parameter system is one of the most flexible in programming languages. You can write functions that accept a fixed number of arguments, a variable number, or even arguments that must be specified by name. This flexibility comes from how Python binds arguments to parameters using both position and name.
Python
# Positional parameters
def introduce(name, age, city):
print(f”{name} is {age} years old and lives in {city}”)
# Arguments must be in the correct order
introduce(“Ali”, 25, “Tehran”) # Correct
introduce(25, “Ali”, “Tehran”) # Wrong order! Will cause errors
Python
def describe_pet(animal, name, age):
print(f”{name} is a {age}-year-old {animal}”)
# Positional arguments (order matters)
describe_pet(“dog”, “Max”, 5)
# Keyword arguments (order doesn’t matter)
describe_pet(name=”Luna”, age=3, animal=”cat”)
describe_pet(animal=”bird”, name=”Tweety”, age=2)
# Mix positional and keyword (positional first, then keyword)
describe_pet(“hamster”, age=1, name=”Nibbles”)
Python
# This works:
describe_pet(“dog”, age=5, name=”Max”)
# This fails (positional after keyword):
# describe_pet(animal=”dog”, “Max”, 5) # SyntaxError
Python
def greet(name, greeting=”Hello”):
print(f”{greeting}, {name}!”)
# Using the default value
greet(“Ali”) # Hello, Ali!
# Providing a custom value
greet(“Sara”, “Hi”) # Hi, Sara!
greet(“Reza”, greeting=”Hey”) # Hey, Reza!
# Multiple default parameters
def create_profile(name, age=18, city=”Unknown”):
return {“name”: name, “age”: age, “city”: city}
print(create_profile(“Ali”))
print(create_profile(“Sara”, 25))
print(create_profile(“Reza”, city=”Shiraz”))
🕯️ Magic Note
Default parameters are evaluated once when the function is defined. This means def add(item, lst=[]) creates a single list that is shared across all calls. Use None as the default and create a new list inside the function instead.
Python
# DANGEROUS! Mutable default
def add_item(item, my_list=[]):
my_list.append(item)
return my_list
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] (same list! not a new one!)
print(add_item(3)) # [1, 2, 3]
# The safe way
def add_item_safe(item, my_list=None):
if my_list is None:
my_list = []
my_list.append(item)
return my_list
print(add_item_safe(1)) # [1]
print(add_item_safe(2)) # [2] (new list each time)
Python
def sum_all(*args):
“””Sum any number of arguments”””
return sum(args)
print(sum_all(1, 2, 3)) # 6
print(sum_all(10, 20, 30, 40, 50)) # 150
print(sum_all()) # 0
def average(*numbers):
if not numbers:
return 0
return sum(numbers) / len(numbers)
print(average(5, 10, 15)) # 10.0
print(average(1, 2, 3, 4, 5, 6)) # 3.5
🕯️ Magic Note
The name *args is a convention. The asterisk * is what matters. You could name it *numbers or *items. The args name is just tradition.
Python
def print_info(**kwargs):
for key, value in kwargs.items():
print(f”{key}: {value}”)
print_info(name=”Ali”, age=25, city=”Tehran”)
# name: Ali
# age: 25
# city: Tehran
def create_user(username, **details):
user = {“username”: username}
user.update(details)
return user
user = create_user(“ali123″, age=25, city=”Tehran”, job=”Engineer”)
print(user)
| Order | Parameter Type | Example |
|---|---|---|
| 1 | Positional parameters | def func(a, b, c) |
| 2 | Default parameters | def func(a, b=10, c=20) |
| 3 | *args (variable positional) | def func(a, *args) |
| 4 | Keyword-only parameters | def func(*, d, e) |
| 5 | **kwargs (variable keyword) | def func(a, **kwargs) |
Python
# Complete example with all types
def complex_function(a, b=10, *args, c=20, d, **kwargs):
print(f”a: {a}”)
print(f”b: {b}”)
print(f”args: {args}”)
print(f”c: {c}”)
print(f”d: {d}”)
print(f”kwargs: {kwargs}”)
# Calling the function
complex_function(1, 2, 3, 4, 5, d=30, x=100, y=200)
# a: 1
# b: 2
# args: (3, 4, 5)
# c: 20 (uses default)
# d: 30
# kwargs: {“x”: 100, “y”: 200}
Python
# Parameters after * are keyword-only
def configure(host, port, *, ssl=True, timeout=30):
print(f”Connecting to {host}:{port} (ssl={ssl}, timeout={timeout})”)
# Works
configure(“localhost”, 8080, ssl=False, timeout=60)
configure(“localhost”, 8080, timeout=60, ssl=True)
# Fails (positional argument not allowed for keyword-only)
# configure(“localhost”, 8080, False, 60) # TypeError!
# Another example
def create_point(x, y, *, color=”black”, size=1):
return {“x”: x, “y”: y, “color”: color, “size”: size}
point = create_point(10, 20, color=”red”, size=3)
🕯️ Magic Note
Keyword-only parameters force clarity. When you see create_point(10, 20, color=”red”), you immediately understand what “red” means. Without the keyword, you would have to remember that the third parameter is color.
Python
def add(a, b, c):
return a + b + c
# Unpacking a list into positional arguments
numbers = [1, 2, 3]
result = add(*numbers) # Equivalent to add(1, 2, 3)
print(result) # 6
# Unpacking a tuple
coordinates = (4, 5, 6)
result = add(*coordinates)
# Unpacking a dictionary into keyword arguments
def display(name, age, city):
print(f”{name} is {age} from {city}”)
person = {“name”: “Ali”, “age”: 25, “city”: “Tehran”}
display(**person) # Equivalent to display(name=”Ali”, age=25, city=”Tehran”)
# Combining unpacking with other arguments
def multiply(a, b, c=1):
return a * b * c
nums = [2, 3]
print(multiply(*nums, c=4)) # 2 * 3 * 4 = 24
- 1. Positional parameters (no defaults)
- 2. Default parameters (with defaults)
- 3. *args (variable positional)
- 4. Keyword-only parameters (after * or *args)
- 5. **kwargs (variable keyword)
Python
# Correct order examples
def f1(a, b, c=1): # positional, then default
def f2(a, b=1, *args): # positional, default, then *args
def f3(a, b=1, *, c=2): # positional, default, *, keyword-only
def f4(a, *args, **kwargs): # positional, *args, **kwargs
# Wrong order examples (SyntaxError)
# def f5(a=1, b): # default then positional
# def f6(a, *args, b=1): # default after *args (but keyword-only after *args is fine!) wait… this is allowed
# Actually, default parameters can come after *args? No, they cannot.
# Let me clarify: positional, default, *args, keyword-only, **kwargs
- Using mutable default parameters (def f(lst=[]))
- Putting parameters with defaults before parameters without defaults
- Forgetting that *args collects all remaining positional arguments
- Confusing *args (in definition) with *list (in call)
- Using **kwargs and expecting ordered arguments (dictionaries have no order before Python 3.7)
- Putting positional arguments after keyword arguments in function calls
| Parameter Type | Best Used When |
|---|---|
| Positional | The order is obvious and natural (like coordinates, division) |
| Default | Most calls use a common value (like timeout, retry count) |
| *args | You need to accept any number of positional arguments (like sum, max) |
| Keyword-only | You want to force clarity and prevent order mistakes |
| **kwargs | You need to pass through arbitrary options to another function |
- What is the difference between a positional argument and a keyword argument?
- What is the problem with def add_item(item, items=[])?
- Write a function that accepts any number of numbers and returns their product.
- How do you make a parameter keyword-only?
- What is the correct order of parameter types in a function definition?
- How do you unpack a list into positional arguments when calling a function?
⚡ Whisper
Parameters are the hands of your function. They reach out and take what the caller gives. Some hands expect to hold specific things in a specific order. Those are positional hands. Some hands have names and do not care about order. Those are keyword hands. Some hands are empty, ready to catch any number of items. Those are *args hands. Some hands catch named things and hold them in a dictionary. Those are **kwargs hands. And some hands have a default grip, holding a familiar object unless something else is given. Design your parameters with care. Think about how others will call your function. Will they remember the order? Will they appreciate keyword clarity? Do you need flexibility? Each choice shapes the user experience of your function. A well-designed parameter list makes a function a joy to use. A poorly designed one creates confusion and bugs. Choose wisely. Your callers will thank you.