Python Function Arguments
When working with functions in Python, understanding how to pass information to them is essential. Function arguments (sometimes called parameters) allow us to send data to functions, making them more flexible and reusable. In this tutorial, we'll explore the various ways to define and use function arguments in Python.
Introduction to Function Arguments
In Python, arguments are values that we pass to functions when calling them. They allow functions to work with external data and produce different results based on the inputs. Python offers several ways to define and pass arguments, giving you flexibility in how you design your functions.
Let's start with the basics and gradually explore more advanced argument types.
Basic Function Arguments
Positional Arguments
The most straightforward way to pass arguments is through positional arguments. The order of the arguments matters, as Python assigns them to the function parameters in the order they appear.
def greet(name, message):
print(f"Hello {name}, {message}")
# Calling the function with positional arguments
greet("Alice", "welcome to Python!")
Output:
Hello Alice, welcome to Python!
In this example, "Alice" is assigned to name
and "welcome to Python!" is assigned to message
.
Keyword Arguments
Keyword arguments allow you to specify which parameter each argument corresponds to, regardless of their order.
def calculate_total(price, quantity, discount):
total = price * quantity * (1 - discount)
return total
# Using keyword arguments
total = calculate_total(price=10.99, quantity=5, discount=0.15)
print(f"Total cost: ${total:.2f}")
# The order doesn't matter with keyword arguments
total = calculate_total(discount=0.15, quantity=5, price=10.99)
print(f"Total cost: ${total:.2f}")
Output:
Total cost: $46.71
Total cost: $46.71
As you can see, both function calls produce the same result despite the different order of arguments.
Default Parameter Values
Default parameters allow a function to have optional arguments by providing default values.
def greet(name, message="Good day!"):
print(f"Hello {name}, {message}")
# Call with both arguments
greet("Bob", "have a nice day!")
# Call with only the required argument
greet("Charlie")
Output:
Hello Bob, have a nice day!
Hello Charlie, Good day!
When we don't provide the message
argument, the function uses "Good day!" as the default value.
Important rules for default parameters:
- Default parameters must come after regular parameters
- Default values are evaluated only once when the function is defined
# This is correct
def func(a, b=5, c=10):
pass
# This will cause a SyntaxError
def func(a=5, b): # Error: non-default parameter follows default parameter
pass
Common Mistake with Mutable Default Values
Be careful when using mutable objects (like lists or dictionaries) as default values:
def add_item(item, shopping_list=[]):
shopping_list.append(item)
return shopping_list
print(add_item("Apple"))
print(add_item("Banana"))
print(add_item("Orange"))
Output:
['Apple']
['Apple', 'Banana']
['Apple', 'Banana', 'Orange']
Notice how the list keeps growing! This happens because the default value is created only once when the function is defined. To avoid this, use None
as the default and create a new list inside the function:
def add_item(item, shopping_list=None):
if shopping_list is None:
shopping_list = []
shopping_list.append(item)
return shopping_list
print(add_item("Apple"))
print(add_item("Banana"))
print(add_item("Orange"))
Output:
['Apple']
['Banana']
['Orange']
Arbitrary Arguments (*args and **kwargs)
Arbitrary Positional Arguments (*args)
Sometimes you may want a function to accept any number of positional arguments. The *args
syntax allows this:
def calculate_sum(*numbers):
total = 0
for num in numbers:
total += num
return total
print(calculate_sum(1, 2))
print(calculate_sum(1, 2, 3, 4, 5))
print(calculate_sum())
Output:
3
15
0
The *numbers
parameter collects all positional arguments into a tuple called numbers
.
Arbitrary Keyword Arguments (**kwargs)
Similarly, **kwargs
allows a function to accept any number of keyword arguments:
def student_info(**kwargs):
print("Student Information:")
for key, value in kwargs.items():
print(f"{key}: {value}")
student_info(name="Alice", age=21, major="Computer Science", gpa=3.8)
Output:
Student Information:
name: Alice
age: 21
major: Computer Science
gpa: 3.8
The **kwargs
parameter collects all keyword arguments into a dictionary.
Combining Parameter Types
You can mix different parameter types in a function definition, but they must appear in the correct order:
- Regular positional parameters
*args
parameters- Keyword parameters with default values
**kwargs
parameters
def function_with_all_args(a, b, *args, option=True, **kwargs):
print(f"a: {a}")
print(f"b: {b}")
print(f"args: {args}")
print(f"option: {option}")
print(f"kwargs: {kwargs}")
function_with_all_args(1, 2, 3, 4, 5, option=False, x=100, y=200)
Output:
a: 1
b: 2
args: (3, 4, 5)
option: False
kwargs: {'x': 100, 'y': 200}
Keyword-Only Arguments
Python 3 introduced keyword-only arguments, which must be specified by name when calling the function:
def process_data(data, *, format=None, strict=False):
"""The parameters after * must be passed as keywords."""
print(f"Processing {data} with format={format} and strict={strict}")
# This works:
process_data([1, 2, 3], format="json", strict=True)
# This raises a TypeError:
try:
process_data([1, 2, 3], "json", True)
except TypeError as e:
print(f"Error: {e}")
Output:
Processing [1, 2, 3] with format=json and strict=True
Error: process_data() takes 1 positional argument but 3 were given
The *
in the function definition indicates that all parameters after it are keyword-only.
Positional-Only Parameters (Python 3.8+)
Python 3.8 introduced positional-only parameters, which must be passed by position and not by keyword:
def divide(a, b, /):
return a / b
# This works:
print(divide(10, 2))
# This raises a TypeError:
try:
print(divide(a=10, b=2))
except TypeError as e:
print(f"Error: {e}")
Output:
5.0
Error: divide() got some positional-only arguments passed as keyword arguments: 'a, b'
The /
in the function definition indicates that all parameters before it are positional-only.
Unpacking Arguments
Python allows you to unpack sequences and dictionaries into function arguments:
Unpacking a List/Tuple
def add(a, b, c):
return a + b + c
numbers = [1, 2, 3]
print(add(*numbers)) # Equivalent to add(1, 2, 3)
Output:
6
Unpacking a Dictionary
def create_profile(username, email, age):
return f"User {username} ({email}) is {age} years old"
user_data = {
"username": "pythonista",
"email": "[email protected]",
"age": 25
}
print(create_profile(**user_data))
Output:
User pythonista ([email protected]) is 25 years old
Real-World Examples
Data Processing Function
def analyze_sales_data(data, *, period="monthly", category=None, include_tax=True):
"""
Analyze sales data with various options.
Args:
data: The sales data to analyze
period: Time period for analysis (daily, monthly, yearly)
category: Product category filter (None for all categories)
include_tax: Whether to include tax in calculations
Returns:
Analysis results dictionary
"""
print(f"Analyzing sales for {period} period")
if category:
print(f"Filtering by category: {category}")
tax_status = "including" if include_tax else "excluding"
print(f"Calculations {tax_status} tax")
# Simulate analysis process
result = {
"total_sales": sum(item["amount"] for item in data),
"period": period,
"tax_included": include_tax
}
return result
# Sample sales data
sales_data = [
{"date": "2023-01-15", "amount": 120.50, "category": "electronics"},
{"date": "2023-01-16", "amount": 75.20, "category": "clothing"},
{"date": "2023-01-16", "amount": 210.75, "category": "electronics"}
]
# Analyze with default parameters
result1 = analyze_sales_data(sales_data)
print(f"Result: {result1}\n")
# Analyze with custom parameters
result2 = analyze_sales_data(
sales_data,
period="daily",
category="electronics",
include_tax=False
)
print(f"Result: {result2}")
Output:
Analyzing sales for monthly period
Calculations including tax
Result: {'total_sales': 406.45, 'period': 'monthly', 'tax_included': True}
Analyzing sales for daily period
Filtering by category: electronics
Calculations excluding tax
Result: {'total_sales': 406.45, 'period': 'daily', 'tax_included': False}
Configuration Builder with Arbitrary Arguments
def build_config(app_name, version, **options):
"""
Build a configuration dictionary with any number of options.
"""
# Start with default configuration
config = {
"app_name": app_name,
"version": version,
"debug": False,
"log_level": "INFO",
"max_connections": 100
}
# Update with provided options
config.update(options)
# Return formatted configuration string
result = f"Configuration for {app_name} v{version}:\n"
for key, value in config.items():
result += f" - {key}: {value}\n"
return result
# Build basic configuration
basic = build_config("MyApp", "1.0")
print(basic)
# Build configuration with custom options
custom = build_config(
"AdvancedApp",
"2.5.1",
debug=True,
log_level="DEBUG",
max_connections=200,
database="postgres",
api_key="abc123",
timeout=30
)
print(custom)
Output:
Configuration for MyApp v1.0:
- app_name: MyApp
- version: 1.0
- debug: False
- log_level: INFO
- max_connections: 100
Configuration for AdvancedApp v2.5.1:
- app_name: AdvancedApp
- version: 2.5.1
- debug: True
- log_level: DEBUG
- max_connections: 200
- database: postgres
- api_key: abc123
- timeout: 30
Summary
Python provides a flexible system for working with function arguments:
- Positional arguments are passed in order
- Keyword arguments are specified by name and can be in any order
- Default parameters make arguments optional
- Arbitrary positional arguments (
*args
) allow passing any number of positional arguments - Arbitrary keyword arguments (
**kwargs
) allow passing any number of keyword arguments - Keyword-only arguments must be specified by name
- Positional-only arguments (Python 3.8+) must be passed by position
- Argument unpacking lets you expand sequences (
*
) and dictionaries (**
) into function arguments
Understanding these argument types will help you write more flexible, reusable Python functions and better understand code written by others.
Practice Exercises
-
Write a function
create_email
that takes required parameters forto
andsubject
, and optional parameters forcc
,bcc
, andattachment
. -
Create a function
calculate_statistics
that accepts any number of numeric values and returns a dictionary containing the count, sum, average, minimum, and maximum values. -
Write a function
make_pizza
that has a required parameter forsize
and accepts any number of toppings using arbitrary arguments. It should print out a description of the pizza. -
Design a function
format_address
that has positional-only parameters for house number and street name, and keyword-only parameters for city, state, and zip code.
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)