PythonProgramming Intermediate

Python Functions: Deep Dive into Arguments & Parameters

TT
TopicTrick
Python Functions: Deep Dive into Arguments & Parameters

What are Python Functions?

A Python function is a named, reusable block of code that performs a specific task, accepts inputs (parameters), and optionally returns an output. Functions are the primary tool for organising logic, avoiding repetition, and making code testable.

Introduction to Python Functions

A function is a reusable block of code designed to perform a single, related action. Functions provide better modularity for your application and a high degree of code reusability.

As you’ve already seen, Python gives you many built-in functions like print() and len(), but you can also create your own functions—these are called user-defined functions.


Why Use Functions?

  1. Reusability: Write once, use many times. This saves space and prevents "copy-paste" errors.
  2. Modularity: Break down complex problems into smaller, manageable chunks. This makes debugging much easier.
  3. Abstraction: Once a function is defined, you only need to know its input and output, not the complex logic inside. It acts as a "black box."

Defining a Function in Python

To define a function, you use the def keyword followed by the function name and parentheses ().

The Basic Structure:

  • def Keyword: Starts the function definition.
  • Function Name: A unique identifier for the function.
  • Parameters: Inputs listed inside the parentheses (optional).
  • Docstring: An optional string describing what the function does.
  • Indented Block: The actual logic of the function.
  • return Statement: Sends a result back to the caller.
python

Pro Tip: Docstrings

Always include a docstring for your functions. It helps other developers (and your future self) understand the purpose of the code without reading the logic.


    Function Arguments & Parameters

    Arguments are the values passed into the function when it is called. Python uses Call by Object Reference, meaning:

    • Immutable Objects (int, str, tuple): Behave like "Pass by Value." Changes inside the function don't affect the original.
    • Mutable Objects (list, dict): Behave like "Pass by Reference." Changes inside the function will affect the original.

    Types of Arguments

    TypeDescription
    RequiredMust be passed in the correct positional order.
    KeywordPassed with an identifier (key=value), allowing any order.
    DefaultHave a predefined value if no argument is provided.
    Variable LengthHandle an arbitrary number of inputs using *args and **kwargs.

    1. Required & Keyword Arguments

    python

    2. Variable Length Arguments: *args and **kwargs

    Sometimes you don't know how many arguments will be passed. Python handles this with:

    • *args: Receives arguments as a Tuple.
    • **kwargs: Receives arguments as a Dictionary.
    python

    3. Special Parameters (Python 3.8+)

    Python allows you to restrict how arguments are passed:

    • Positional-Only (/): Parameters before / must be positional.
    • Keyword-Only (*): Parameters after * must be keyword-based.
    python

    Anonymous Functions: Lambda Expressions

    A Lambda function is a small, one-line function without a name. They are often used for short-lived tasks or as arguments to higher-order functions like sort().

    python

    Caution with Mutable Defaults

    Avoid using mutable objects like empty lists `[]` or dictionaries `{}` as default arguments. They are initialized only once, meaning data will persist between multiple function calls!


      4. Default Arguments and Type Hints

      Default arguments make parameters optional by supplying a fallback value. Type hints (Python 3.5+) document the expected types without enforcing them:

      python

      Type hints are especially useful in larger codebases and are read by tools like mypy and editors like VS Code for autocomplete.

      5. Higher-Order Functions

      Functions in Python are first-class objects — you can pass them as arguments, return them, or store them in variables. This enables powerful patterns:

      python

      Real-World Example: A Data Validator

      Combining everything — default args, *args, type hints, and return values:

      python

      Related Python Topics

      For the official reference, see the Python Functions documentation and the section on lambda expressions.

      Conclusion

      Functions are the building blocks of any robust Python application. By mastering parameters, arguments, and return types, you can write cleaner, more efficient, and modular code.

      What's Next?

      Move on to Python Scope & LEGB Rule to understand how variables are accessed within and outside these functions.

        Common Mistakes with Python Functions and Parameters

        1. Mutable default arguments Defining def append_item(item, lst=[]) creates a single list shared across all calls. The default is evaluated once when the function is defined, not on each call. The fix is def append_item(item, lst=None) with lst = lst if lst is not None else [] inside the body. This is one of the most frequently cited Python gotchas — see Python's common pitfalls.

        2. Modifying a list argument in place When you pass a list to a function and mutate it with .append(), .sort(), or index assignment, the change is visible to the caller because Python passes object references. If mutation is unintended, create a copy: lst = lst[:] or lst = list(original) at the start of the function.

        3. Using *args and **kwargs without documenting them *args collects positional overflow into a tuple; **kwargs collects keyword overflow into a dict. Functions that accept both become hard to call without documentation. Always add a docstring explaining which keys **kwargs expects, or replace open-ended **kwargs with explicit named parameters when the set of options is known.

        4. Calling keyword-only arguments positionally After a bare * in a function signature — def f(a, *, b)b must always be passed as a keyword argument. Attempting f(1, 2) raises a TypeError. This is intentional: keyword-only arguments make call sites self-documenting. See PEP 3102 — Keyword-Only Arguments.

        5. Forgetting that functions are first-class objects A function defined with def is an object that can be stored in a variable, passed as an argument, or returned from another function. Forgetting this leads to verbose code where a simple map(str, numbers) or sorted(items, key=lambda x: x.date) would suffice. The Python functional programming HOWTO covers these patterns.

        Frequently Asked Questions

        What is the difference between *args and **kwargs? *args captures any number of positional arguments beyond the named parameters into a tuple. **kwargs captures any number of keyword arguments into a dictionary. They are used together to write flexible functions that accept variable input, such as decorators and wrapper functions. You can name them anything — *args and **kwargs are conventions, not keywords. The Python function definition syntax documents all parameter forms.

        What is a lambda function and when should I use it? A lambda is an anonymous single-expression function: square = lambda x: x ** 2. Use lambdas for short, throwaway functions passed to higher-order functions like sorted, map, and filter. Avoid lambdas for anything complex enough to warrant a name or a docstring — use a regular def in those cases. The Python lambda expressions documentation explains the restrictions (no statements, single expression only).

        How do I return multiple values from a Python function? Return a tuple: return x, y (the parentheses are optional). The caller can unpack it: a, b = my_function(). For functions returning many values, a namedtuple or dataclass makes the return value self-documenting: return Point(x=1, y=2). See the collections.namedtuple documentation for a lightweight alternative to a full class.