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")
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()
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 using nonlocal
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()
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'
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.
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.
Suggested Quiz
6 Questions
What is an inner function in Python?
-
A function that is called from within a class
-
A function defined inside another function
-
A function that inherits from another function
-
A function used only with classes
Explanation:
An inner function is defined within another function and can access the outer function’s variables.
When defining an inner function, what is the scope of variables from the outer function?
-
They are accessible only if passed as parameters.
-
They are accessible and can be modified directly.
-
They are not accessible at all.
-
They are accessible but cannot be modified without special handling.
What will the following code output?
def outer():
def inner():
return "Hello from inner"
return inner()
print(outer())
Explanation:
The outer() function defines inner() and immediately calls it, returning its result.
What is the scope of a variable declared inside an inner function?
-
-
Local to the outer function
-
Local to the inner function
-
Explanation:
A variable inside an inner function is local to that function and not accessible outside it unless returned.
Which of the following best describes the LEGB rule in Python?
-
It describes the order of function execution.
-
It outlines the scope resolution order Local, Enclosing, Global, Built-in.
-
It defines the rules for variable naming.
-
It specifies the data types available in Python.
Can an inner function access variables from the enclosing function?
-
No, Python does not support this
-
-
-
Only if passed explicitly as arguments
Explanation:
Python supports lexical scoping, allowing inner functions to access variables from the outer function.
Quiz Completed Successfully
Your Score : 2/6
Accuracy : 0%
Login to View Explanation
1/6
1/6
< Previous
Next >