Python Functions

Python Functions

Kishore V


Python Functions

A function is a reusable block of code that performs a specific task. A function runs only when it is called, making programs more organized, readable, and efficient.

Functions help you:

    • Avoid repeating the same code

    • Break large programs into smaller parts

    • Make code easier to maintain and debug

Creating a Function

In Python, functions are created using the def keyword, followed by a function name and parentheses.

Syntax

Try it Yourself

Example: Simple Function

Try it Yourself

This defines a function named show_message. The code inside the function is indented to indicate it belongs to the function.

Calling a Function

A function does nothing until it is called. To call a function, write its name followed by parentheses.

Example

Try it Yourself

Calling a Function Multiple Times

Once defined, a function can be reused any number of times.

Example

Try it Yourself

Each function call executes the same block of code.

Function Naming Rules

Function names follow the same naming rules as variables:

    • Must start with a letter or an underscore (_)

    • Can include letters, numbers, and underscores

    • Are case-sensitive

    • Should be descriptive and meaningful

Examples of Valid Function Names

Try it Yourself

Why Use Functions?

Without functions, repeating the same logic leads to messy and inefficient code.

Example: Without Using Functions

Try it Yourself

Using Functions for Reusability

With functions, you write the logic once and reuse it easily.

Example: Using a Function

Try it Yourself

This approach reduces duplication and improves clarity.

Return Values in Functions

Functions can send data back using the return statement. Once return is executed, the function stops running.

Example: Function Returning a Value

Try it Yourself

Using Returned Values Directly

You can also use the returned value immediately.

Example

Try it Yourself

Functions Without a Return Statement

If a function does not explicitly return a value, Python returns None by default.

Example

Try it Yourself

Output:
None

The pass Statement in Functions

A function definition cannot be empty. If you want to define a function but implement it later, use the pass statement.

Example

Try it Yourself

Note: The pass keyword acts as a placeholder and avoids syntax errors during development.

Function Arguments in Python

Arguments are values that you pass to a function so it can work with data. They are written inside the parentheses when calling a function.

A function can accept one or more arguments, separated by commas.

Function with a Single Argument

Example

Try it Yourself

Here, username receives the value passed during each function call.

Parameters vs Arguments

Although often used interchangeably, there is a small technical difference:

    • Parameter → The variable listed in the function definition

    • Argument → The actual value passed when calling the function

Example

Try it Yourself

Required Number of Arguments

By default, the number of arguments passed must match the number of parameters.

Correct Usage

Try it Yourself

Incorrect Usage (Error)

Try it Yourself

Note: This will raise a TypeError.

Default Parameter Values

You can assign default values to parameters. If no argument is provided, the default value is used.

Example

Try it Yourself

Example: Default Country

Try it Yourself

Keyword Arguments

With keyword arguments, you specify the parameter name along with the value. This makes the order irrelevant.

Example

Try it Yourself

Positional Arguments

Arguments passed without keywords are called positional arguments. Their order matters.

Example

Try it Yourself

Order Change Affects Output

Try it Yourself

Mixing Positional and Keyword Arguments

You can combine both types, but positional arguments must come first.

Example

Try it Yourself

Passing Different Data Types as Arguments

Python functions can accept any data type.

Example: Passing a List

Try it Yourself

Example: Passing a Dictionary

Try it Yourself

Returning Values from Functions

Functions can send data back using the return statement.

Example

Try it Yourself

Returning Different Data Types

Example: Returning a List

Try it Yourself

Example: Returning a Tuple

Try it Yourself

Positional-Only Arguments

You can restrict parameters to accept only positional arguments using /.

Example

Try it Yourself

Keyword-Only Arguments

To allow only keyword arguments, use * before parameters.

Example

Try it Yourself

Combining Positional-Only and Keyword-Only Arguments

You can use both in the same function.

Example

Try it Yourself

Python *args and **kwargs

Normally, Python functions must be called with the exact number of arguments defined in the function.

But in real-world programs, you may not always know how many values will be passed.

Python solves this problem using:

    • *args → for variable positional arguments

    • **kwargs → for variable keyword arguments

These make functions flexible and reusable.

Arbitrary Positional Arguments (*args)

When you prefix a parameter with *, the function can accept any number of positional arguments.

All values passed this way are stored as a tuple inside the function.

Example: Using *args

Try it Yourself

Here, names becomes a tuple:

("Arjun", "Neha", "Rohan")

Understanding *args

Inside the function:

args is a tuple. You can loop through it or access elements by index.

Example

Try it Yourself

Using *args with Regular Parameters

Normal parameters must come before *args.

Example

Try it Yourself

message gets "Welcome". Remaining values go into users.

Practical Uses of *args

Example: Adding Multiple Numbers

Try it Yourself

Example: Finding the Largest Number

Try it Yourself

Arbitrary Keyword Arguments (**kwargs)

When you prefix a parameter with **, the function can accept any number of keyword arguments. Inside the function, these values are stored as a dictionary.

Example: Using **kwargs

Try it Yourself

Here, info becomes: {"name": "Riya", "age": 22, "city": "Jaipur"}

Understanding **kwargs

You can access values using dictionary keys.

Example

Try it Yourself

Using **kwargs with Regular Parameters

Normal parameters must appear before **kwargs.

Example

Try it Yourself

Combining *args and **kwargs

You can use both in the same function.

Correct Order:

    1. Regular parameters

    2. *args

    3. **kwargs

Example

Try it Yourself

Unpacking Arguments

The * and ** symbols can also be used when calling functions to unpack values.

Example: Unpacking a List with *

Try it Yourself

This is the same as: multiply(2, 3, 4)

Example: Unpacking a Dictionary with **

Try it Yourself

This is the same as: welcome_user(first="Amit", last="Verma")

Variable Scope in Python

In Python, a variable’s scope determines where that variable can be accessed in a program. A variable is only available within the region where it is created. Understanding scope helps prevent unexpected errors and makes your code easier to manage.

Local Scope

A variable created inside a function belongs to the local scope. It can be accessed only within that function.

Example: Local Variable

Try it Yourself

Here, value exists only inside the calculate() function.

Accessing Local Variables in Nested Functions

A local variable can be accessed by inner functions defined inside the same outer function.

Example

Try it Yourself

The variable message is available to inner_function() because it is inside the enclosing scope.

Global Scope

A variable created outside any function belongs to the global scope. Global variables can be accessed from anywhere in the program.

Example: Global Variable

Try it Yourself

Both the function and the main program can access count.

Local vs Global Variables with Same Name

If a variable with the same name exists both inside and outside a function, Python treats them as separate variables.

Example

Try it Yourself

    • Inside the function → local variable

    • Outside the function → global variable

They do not affect each other.

The global Keyword

The global keyword allows a function to create or modify a global variable.

Example: Creating a Global Variable Inside a Function

Try it Yourself

Example: Modifying a Global Variable

Try it Yourself

Note: Without global, Python would create a new local variable instead of modifying the global one.

The nonlocal Keyword

The nonlocal keyword is used in nested functions to modify a variable from the enclosing (outer) function, but not the global scope.

Example

Try it Yourself

Here, nonlocal allows update_name() to change the value of username in the outer function.

The LEGB Rule

Python follows the LEGB rule when searching for a variable:

    1. L – Local → Inside the current function

    2. E – Enclosing → Inside outer functions

    3. G – Global → At the top level of the module

    4. B – Built-in → Python’s built-in names

Example: LEGB in Action

Try it Yourself

Output:
Inner: Local value
Outer: Enclosing value
Global: Global value

Python always picks the closest matching scope.

Python Decorators

A decorator allows you to add extra behavior to a function without modifying the function’s original code.

In simple terms:

    • A decorator is a function

    • It takes another function as input

    • It returns a new enhanced function

Decorators are commonly used for logging, validation, authentication, caching, and formatting output.

Basic Decorator Concept

A decorator wraps a function and adds new behavior before or after calling it.

Example: Simple Decorator

Try it Yourself

How It Works:

    • make_upper is the decorator

    • greet is the function being decorated

    • greet() is replaced with wrapper()

Using the Same Decorator on Multiple Functions

A decorator can be reused for many functions.

Example

Try it Yourself

Decorating Functions with Arguments

If the original function accepts arguments, the wrapper must accept them too.

Example

Try it Yourself

Using *args and **kwargs in Decorators

To make decorators flexible and compatible with any function signature, use *args and **kwargs.

Example

Try it Yourself

This allows the decorator to work with any number of arguments.

Decorators with Their Own Arguments

Sometimes, decorators themselves need parameters. This requires an extra level of wrapping.

Example: Decorator Factory

Try it Yourself

Using Multiple Decorators on a Function

You can stack multiple decorators on a single function. Decorators are applied from bottom to top.

Example

Try it Yourself

Execution Order:

    • add_prefix runs first

    • make_upper runs second

Preserving Function Metadata

Decorators replace the original function, which causes metadata like __name__ and __doc__ to be lost.

Example: Metadata Loss

Try it Yourself

Fixing Metadata with functools.wraps

Python provides functools.wraps to preserve original function information.

Example

Try it Yourself

Now the function keeps its original identity.

Lambda Functions in Python

A lambda function is a small, unnamed function created using the lambda keyword. It is mainly used for short operations where defining a full function would be unnecessary.

Lambda functions can accept any number of arguments, but they must contain only one expression, and that expression is automatically returned.

Syntax

lambda parameters : expression

The expression is evaluated and its result is returned.

Simple Lambda Example

Try it Yourself

Lambda with Multiple Arguments

Examples

Try it Yourself

Why Use Lambda Functions?

Lambda functions are most useful when you need a temporary, small function, especially inside another function. Consider a function that returns another function, where the multiplier is decided later.

Returning a Lambda from a Function

Example

Try it Yourself

When to Use Lambda Functions

Use lambda functions when:

    • The function is simple and short

    • The function is used only once

    • You want cleaner and more readable code

Lambda with Built-in Functions

Lambda functions are often combined with built-in functions such as map(), filter(), and sorted().

Using Lambda with map()

The map() function applies a function to each item in a list.

Example: Square all numbers in a list

Try it Yourself

Using Lambda with filter()

The filter() function selects items that match a condition.

Example: Keep numbers greater than 10

Try it Yourself

Using Lambda with sorted()

The sorted() function can use a lambda to define custom sorting rules.

Example: Sort a list of dictionaries & Words

Try it Yourself

Recursion in Python

Recursion is a programming technique where a function calls itself to solve a problem by breaking it into smaller subproblems. Instead of using loops, recursion repeatedly applies the same logic until a stopping condition is reached.

Note: When used carefully, recursion can make code clean, readable, and mathematically elegant. However, incorrect recursion can lead to infinite function calls or excessive memory usage, so it must always be written with care.

Simple Recursion Example

Below is a recursive function that prints numbers from a given value down to 1.

Try it Yourself

Base Case and Recursive Case

Every recursive function must contain two essential parts:

    1. Base Case: A condition that stops the recursion.

    2. Recursive Case: The part where the function calls itself with a modified value.

Without a base case, the function would keep calling itself forever.

Example: Factorial Using Recursion

The factorial of a number is calculated as: n! = n × (n - 1)!

Try it Yourself

Why the Base Case Matters

The base case ensures that the recursion eventually stops. Always verify that your recursive calls move closer to this condition.

Fibonacci Sequence Using Recursion

The Fibonacci sequence is a well-known series where each number is the sum of the two previous numbers: 0, 1, 1, 2, 3, 5, 8, ...

Recursive Fibonacci Example

Find the 8th Fibonacci number:

Try it Yourself

Using Recursion with Lists

Recursion can also be applied to process collections such as lists by handling one element at a time.

Example: Sum of List Elements

Try it Yourself

Example: Find the Largest Number in a List

Try it Yourself

Recursion Depth Limit in Python

Python limits how deep recursion can go to prevent crashes caused by excessive memory usage. By default, this limit is usually around 1000 function calls.

Check the Current Recursion Limit

Try it Yourself

Increase the Recursion Limit (Use with Caution)

Try it Yourself

Generators in Python

Generators are special functions that produce values one at a time and pause their execution between each value. Instead of returning all results at once, they generate values on demand, making them highly memory-efficient.

When a generator function is called, it does not execute immediately. Instead, it returns a generator object, which can be iterated over like an iterator.

Basic Generator Example

A generator uses the yield keyword instead of return.

Try it Yourself

Here, values are produced one by one as the loop iterates.

The yield Keyword

The yield keyword pauses the function, saves its current state, and returns a value. Execution resumes from the same point the next time the generator is accessed.

Example: Generator That Counts Down

Try it Yourself

Unlike return, yield allows the function to continue execution later.

Why Generators Save Memory

Generators do not store all values in memory. They generate values only when needed, which is ideal for large datasets.

Example: Large Range Generator

Try it Yourself

Even though the range is large, memory usage stays low.

Using next() with Generators

You can manually retrieve values from a generator using next().

Try it Yourself

When no values remain, Python raises a StopIteration exception.

StopIteration Example

Try it Yourself

Generator Expressions

Generator expressions are similar to list comprehensions, but they use parentheses and do not create a list in memory.

List vs Generator Expression

Try it Yourself

Generator Expression with sum()

Try it Yourself

This computes the result without creating an intermediate list.

Fibonacci Sequence Using a Generator

Generators are perfect for infinite sequences like Fibonacci numbers.

Try it Yourself

This can run indefinitely without exhausting memory.

Advanced Generator Methods

Generators support additional methods for more control.

send() Method

The send() method sends a value into the generator.

Try it Yourself

close() Method

The close() method stops the generator’s execution.

Try it Yourself

Our website uses cookies to enhance your experience. Learn More
Accept !