Open In App

Python Inner Functions

Last Updated : 27 Feb, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

In Python, a function inside another function is called an inner function or nested function. Inner functions help in organizing code, improving readability and maintaining encapsulation. They can access variables from the outer function, making them useful for implementing closures and function decorators.

Example:

Python
def fun1(msg): # outer function
    
    def fun2(): # inner function
        print(msg)
    fun2()

fun1("Hello")

Output
Hello

Explanation: Here, fun2() is definedinside fun1() and it accesses the variable msg from the enclosing scope.

Why Use Inner functions?

Inner functions provide several advantages:

  • Encapsulation: They help hide the inner logic from external access.
  • Code Organization: They make the code cleaner by grouping related functionality.
  • Access to Enclosing Scope: Inner functions can access variables of the outer function.
  • Closures: They allow functions to retain the state of their enclosing function even after execution.

Scope of variables in inner functions

Inner functions can access variables from their enclosing (outer) function, but modifying them requires special handling. This follows Python’s LEGB rule (Local, Enclosing, Global, Built-in) for variable scope.

Example 1 : Local Variable Access

Python
def fun1(): # outer function
    msg = "Geeks for geeks"
    
    def fun2(): # inner function
        print(msg)  # accessing outer function's variable
    
    fun2()
fun1()

Output
Geeks for geeks

Explanation: fun1() defines a local variable msg and an inner function fun2(), which prints msg. Due to lexical scoping, fun2() accesses msg from fun1(). Calling fun1() invokes fun2(), printing the message.

Example 2: Modifying variables usingnonlocal

Python
def fun1(): # outer function
    a = 45
    
    def fun2(): # inner function
        nonlocal a  # allows modification of `a` from fun1
        a=54
        print(a)
    
    fun2()
    print(a)

fun1()

Output
54
54

Explanation: nonlocal keyword allows fun2() to modify the variable a from fun1(). Without nonlocal, a inside fun2() would be treated as a new local variable instead of modifying the one in fun1().

Example 3 : closure in inner function

Python
def fun1(a): # outer function
    
    def fun2(): # inner function
        print(a)
    return fun2  # returning function without parentheses

closure_func = fun1("Hello, Closure!")
closure_func()  # inner function remembers 'a'

Output
Hello, Closure!

Explanation: Even after fun1() completes execution, the returned fun2() function retains access to a, demonstrating a closure.

Real – World Applications of inner functions

Inner functions are useful in real-world scenarios for better code organization, encapsulation and reusability. Below are some practical applications:

Example1 : Encapsulation of helper functions

Python
def process_data(data):
    # removes extra spaces from a list
    
    def clean_data():
        return [item.strip() for item in data]  # Strip spaces
    
    return clean_data()  # return cleaned list

print(process_data(["  Python  ", "  Inner Function  "]))  

Output
['Python', 'Inner Function']

Explanation: process_data(data) removes leading and trailing whitespace from each string in the input list. It defines a nested function, clean_data(), which trims spaces using .strip() and returns the cleaned list.

Example 2 : Function wrapper and logging

Python
import logging

logging.basicConfig(level=logging.INFO)  # configure logging

def logger(func):
    # logs function execution details 
    
    def wrapper(*args, **kwargs):
        logging.info(f"Executing {func.__name__} with {args}, {kwargs}")  # log function call
        return func(*args, **kwargs)  # call original function
    return wrapper

@logger
def add(a, b):
    return a + b  # return sum

print(add(3, 4))  

Output:

INFO:root:Executing add with arguments (3, 4), {}
7

Explanation: logger function, *args captures positional arguments, and **kwargs captures keyword arguments, allowing the wrapper to handle any function signature.

Best Practices for using inner functions

Inner functions are powerful but should be used wisely to maintain code readability, efficiency and maintainability. Below are some best practices:

  • Use inner functions only when necessary: Avoid excessive nesting, as it can reduce readability.
  • Use closures wisely: Ensure that captured variables are managed properly to prevent unintended side effects.
  • Prefer nonlocal over global variables: If modifying outer function variables, use nonlocal instead of global.
  • Use inner functions in decorators: This is a common and effective use case.


Next Article
Article Tags :
Practice Tags :

Similar Reads