Python *args & **kwargs Guide

๐Ÿ Python 3.12+ ๐ŸŸข Chapter 16 of 65 ๐Ÿ“‚ Phase 4: Functions & Reusable Code ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this chapter: *args (Positional Pack) ยท **kwargs (Keyword Pack) ยท Unpacking (* / **) ยท Student Grading Project
Master variable-length arguments in Python: positional packing with *args, keyword packing with **kwargs, unpacking operators, parameter hierarchy rules, and building a student marks management system.
1Variable Positional Arguments: *args (Tuple Packing)

When you do not know in advance how many positional arguments a caller might pass, prefix a parameter with an asterisk: *args.

Python automatically packs all extra positional arguments into an immutable tuple named args:

๐Ÿ’ป Example 1: Dynamic Positional Packing with *args
# Calculate the sum and average of ANY number of arguments:
def calculate_statistics(*numbers):
    if not numbers:
        return 0, 0
    total = sum(numbers)
    avg = total / len(numbers)
    return total, round(avg, 2)

# Call with 2, 4, or 6 arguments seamlessly:
tot1, avg1 = calculate_statistics(10, 20)
tot2, avg2 = calculate_statistics(10, 20, 30, 40)
tot3, avg3 = calculate_statistics(5, 15, 25, 35, 45, 55)

print(f"Call 1 -> Sum: {tot1}, Avg: {avg1}")
print(f"Call 2 -> Sum: {tot2}, Avg: {avg2}")
print(f"Call 3 -> Sum: {tot3}, Avg: {avg3}")
๐Ÿ” Tuple Packing Mechanics:

Inside calculate_statistics, numbers is a tuple (10, 20, 30, 40). You can loop over it, slice it, or pass it to sum() and len().

2Variable Keyword Arguments: **kwargs (Dictionary Packing)

Prefixing a parameter with two asterisks (**kwargs) captures arbitrary named keyword arguments and packs them into a dictionary:

๐Ÿ’ป Example 2: Dynamic Keyword Packing with **kwargs
# Function accepting arbitrary user profile metadata:
def build_user_profile(user_id, **attributes):
    profile = {"id": user_id}
    # kwargs acts as a standard dictionary:
    for key, value in attributes.items():
        profile[key] = value
    return profile

# Call with different optional keyword arguments:
user_a = build_user_profile(101, username="balaji", role="Backend Lead", country="India")
user_b = build_user_profile(102, username="alex", is_active=True)

print("Profile A:", user_a)
print("Profile B:", user_b)
๐Ÿ” Dictionary Inspection:

Inside the function, attributes is a dictionary: {'username': 'balaji', 'role': 'Backend Lead', 'country': 'India'}.

3Standard Parameter Ordering Hierarchy

When combining positional, default, *args, keyword-only, and **kwargs parameters, Python enforces a strict grammatical order:

def function(positional, *args, keyword_only, **kwargs):
๐Ÿ’ป Example 3: Standard Parameter Ordering Hierarchy
def complex_logger(prefix, *messages, level="INFO", **metadata):
    print(f"[{level}] {prefix}:", " ".join(messages))
    if metadata:
        print("  Additional Metadata:", metadata)

# Calling with mixed parameter types:
complex_logger(
    "ServerAPI",
    "Database connection established", "Cache warmed up",
    level="SUCCESS",
    ip="192.168.1.1", port=5432
)
๐Ÿ” Parameter Hierarchy Rule:

*args must come before keyword-only arguments, and **kwargs must ALWAYS be the final parameter in the signature.

4Practical Project 2: Student Marks Management & Grading System

Creating a complete modular student grading system using *args for subject marks and **kwargs for extra academic credentials:

๐Ÿ’ป Example 4: Student Marks Management System Project
# Student Marks Management & Report Generator
def generate_student_report(name, roll_no, *marks, **extra_details):
    total_marks = sum(marks)
    max_possible = len(marks) * 100
    percentage = (total_marks / max_possible) * 100 if max_possible > 0 else 0
    
    # Determine grade:
    if percentage >= 90: grade = "A+ ๐ŸŒŸ"
    elif percentage >= 75: grade = "A โœจ"
    elif percentage >= 60: grade = "B ๐Ÿ‘"
    else: grade = "C โš ๏ธ"
    
    print("=" * 45)
    print(f"๐ŸŽ“ STUDENT REPORT: {name} (Roll #{roll_no})")
    print("=" * 45)
    print(f"โ€ข Subjects Count: {len(marks)}")
    print(f"โ€ข Total Score:    {total_marks}/{max_possible}")
    print(f"โ€ข Percentage:     {percentage:.2f}%")
    print(f"โ€ข Final Grade:    {grade}")
    
    if extra_details:
        print("\n๐Ÿ“Œ Additional Student Info:")
        for key, val in extra_details.items():
            print(f"  - {key.replace('_', ' ').title()}: {val}")
    print("=" * 45)

# Test the student report generator:
generate_student_report(
    "Balaji", 202601,
    95, 88, 92, 85, 98,
    branch="Computer Science", semester="6th Sem", college="JNTU"
)
๐Ÿ” Dynamic Extensibility:

The function accepts any number of subject marks (whether a student took 3 or 8 subjects) and any custom metadata dynamically.

โš ๏ธ Common Developer Pitfall: Placing Positional Parameters After **kwargs

Writing def func(**kwargs, extra): causes a SyntaxError: invalid syntax. **kwargs MUST always be the absolute last parameter in any Python function signature.

๐Ÿ’ป Hands-on Interactive Practice Challenge

Write a function calculate_bill(customer_name, *item_prices, discount=0.10, **store_info) that prints an itemized checkout receipt.

Python 3 Practice Challenge โ–ถ Run in Compiler
def calculate_bill(customer, *prices, discount=0.10, **store_info):
    subtotal = sum(prices)
    discount_amount = subtotal * discount
    final_total = subtotal - discount_amount
    
    print(f"Customer: {customer} | Store: {store_info.get('store_name', 'SuperMart')}")
    print(f"Items: {len(prices)} | Subtotal: Rs.{subtotal}")
    print(f"Final Total (after {discount*100}% discount): Rs.{final_total:.2f}")

calculate_bill("Alex", 120, 450, 300, store_name="City Mega Mart", city="Hyderabad")
Run This Challenge in Online Python IDE โ†’
โ“ Frequently Asked Questions (FAQ)

Q Can I name *args something else like *values?

Yes! The asterisk (*) is what activates tuple packing. You can name the variable *values or *items. However, *args and **kwargs are PEP 8 standard conventions.

Q How do I unpack a list or dictionary into a function call?

Use *my_list to unpack list elements as positional arguments, and **my_dict to unpack dictionary key-value pairs as keyword arguments.

Q Why are *args and **kwargs commonly used in Python Decorators?

Decorators wrap arbitrary functions with unknown signatures. Using (*args, **kwargs) allows the wrapper to forward all arguments to the original function safely.

OC
Written by Our Compiler Technical Editorial Team
Reviewed for accuracy & tested on Python 3.12+ runtime ยท Last updated August 2026