Normally you do it to make closures:

def make_adder(x):
    def add(y):
        return x + y
    return add

plus5 = make_adder(5)
print(plus5(12))  # prints 17

Inner functions can access variables from the enclosing scope (in this case, the local variable x). If you're not accessing any variables from the enclosing scope, they're really just ordinary functions with a different scope.

Answer from Adam Rosenfield on Stack Overflow
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-inner-functions
Python Inner Functions - GeeksforGeeks
May 22, 2026 - In Python, an inner function (also called a nested function) is a function defined inside another function.
Discussions

Thoughts on nested / inner functions in Python for better encapsulation and clarity?
You seem very receptive to feedback and understanding how code “feels” to people, so I’ll be direct. It is hard to get across how much I hate this code. Look at those type hints. So many options! I get that you’re trying to make things flexible, but all of this variety of types makes things so much harder to follow. People end up passing around strings, users, lists of strings, lists of users and nulls all over the place instead of having one clear place for casting. If I want to reuse process_recipients I can’t. If I want to test it, I can’t. You could rename it to something like cast_to_emails_list and have this one reusable “takes anything” function. Your inner functions are more polluted because they have access to more outer scope variables. You’re more likely to be bitten by typos and other mistakes. The keyword only arguments are fine on send_mail since that’s so ripe for mistakes. It’s silly on process_recepients. The likelihood that someone will mix up the order of positional arguments on a function with one argument is… low. Other ways to achieve your goals: Give your functions more descriptive names, as in this name helps me understand what the function does if I didn’t know already. Use a doc string if needed. Give functions a leading underscore to mark them as a private. But consider if you need to do this. You’re not really making someone’s life easier by giving them less tools that are useful. It’s just if you don’t want it to be something supported outside of the scope of that module. __all__ is similar. Have one input type for arguments unless the role of the function is casting/deserialization (single responsibility). It’s fine to have some “helpers” module for stuff that isn’t part of the “main story”. A hint that you’re doing it right is you don’t end up with circular imports there. Check out Grokking Simplicity. I think you’ll like it. You have good instincts, just need to see some ways other people have solved the same problems. More on reddit.com
🌐 r/Python
72
173
January 8, 2023
Is nesting function declarations bad practice?
You're probably wrong. Deep nesting is generally frowned upon, because it tends to make code harder to read; but nesting functions one level deep is hardly "deep nesting", and the benefits (not having those inner functions clutter the global scope) often outweigh the downsides. As always: apply taste. More on reddit.com
🌐 r/Python
8
2
May 27, 2021
Nested Function Best Practices (Python)
This is perfectly good code. I wouldn't ding it in a professional code review. Another option would be to use an underscore to hint that "display" is private: def _Display(node, level=0): if not node: return display(node.left_child, level + 1) print('\t' * level, node) display(node.right_child, level + 1) def print_inorder(self): self._Display(self.node) But your way is also just fine. More on reddit.com
🌐 r/learnprogramming
6
1
April 24, 2019
[Python] Should I use nested functions for this?

I think that’s mostly a style choice. Personally I would keep it outside; IMO it looks cleaner and more organized. Plus you may be coding down the line and realize “hey, I need that for something else” and if you nest it then you won’t be able to use it.

More on reddit.com
🌐 r/learnprogramming
9
3
July 24, 2018
🌐
freeCodeCamp
freecodecamp.org › news › nested-functions-in-python
Nested Functions in Python
January 6, 2020 - There are times when you want to ... encapsulate it within another function. When you nest a function like this, it's hidden from the global scope. Because of this behavior, data encapsulation is sometimes referred to as data ...
🌐
Real Python
realpython.com › inner-functions-what-are-they-good-for
Python Inner Functions: What Are They Good For? – Real Python
2 weeks ago - Unless you need to hide your functions from the outside world, there’s no specific reason to nest them. You could define those functions as non-public top-level functions, and you’d be good to go. In this section, you’ll learn about closure factory functions. Closures are inner functions returned as function objects. Their main feature is that they can access the variables and names defined in the enclosing scope, even though the enclosing function has finished executing. When you return an inner function object, Python packs the function along with its containing environment.
🌐
Reddit
reddit.com › r/python › thoughts on nested / inner functions in python for better encapsulation and clarity?
r/Python on Reddit: Thoughts on nested / inner functions in Python for better encapsulation and clarity?
January 8, 2023 -

Been loving Python for 7+ years not and still going strong. I recently found myself writing more and more inner functions to encapsulate logic easier and make otherwise rather polluting/dead functions stick out less.

I like it, because it allows me to write way cleaner and less bloated code – clustering helper-functions to only where they need to be. Also decreases cognitive load considerably by not having to keep track on where a helper function is being used.

But it has gotten to a point where I'm genuinely concerned, because I have also started defining lambdas in inner-functions too! I know lambda shouldn't be used and PEP checker complains too, but it's so handy when combined with list comprehensions…

What are your thoughts on this?
Do you use nested functions yourself or do you consider it bad practice? Where else do you put helpers?


An example would be the following code:

def send_mail(
    *,
    subject: str,
    body_plain: str,
    send_to: Union[List[str], str, List[User], User],
    send_cc: Optional[Union[List[str], str, List[User], User]] = None,
    send_bcc: Optional[Union[List[str], str, List[User], User]] = None,
    reply_to: Optional[Union[List[str], str, List[User], User]] = None
    ...
) -> None:

    def _process_recipients(*, recipients: Optional[Union[List[str], str, List[User], User]]) -> List[str]:
        """ Process various inputs for `send_to`, `send_cc` and `send_bcc` to a normalized
        output that can be used by the emailing instance aka a list of emails """
        _user_to_email = lambda x: x.email if isinstance(x, User) else x  # transform user objects to mail
        if not recipients: return []  # recipients are empty
        if isinstance(recipients, str) or isinstance(recipients, User):
            recipients = [recipients]
        return [_user_to_email(recipient) for recipient in recipients]

    ...

    send_to = _process_recipients(recipients=send_to)
    send_cc = _process_recipients(recipients=send_cc)
    send_bcc = _process_recipients(recipients=send_bcc)

    ...
Top answer
1 of 29
168
You seem very receptive to feedback and understanding how code “feels” to people, so I’ll be direct. It is hard to get across how much I hate this code. Look at those type hints. So many options! I get that you’re trying to make things flexible, but all of this variety of types makes things so much harder to follow. People end up passing around strings, users, lists of strings, lists of users and nulls all over the place instead of having one clear place for casting. If I want to reuse process_recipients I can’t. If I want to test it, I can’t. You could rename it to something like cast_to_emails_list and have this one reusable “takes anything” function. Your inner functions are more polluted because they have access to more outer scope variables. You’re more likely to be bitten by typos and other mistakes. The keyword only arguments are fine on send_mail since that’s so ripe for mistakes. It’s silly on process_recepients. The likelihood that someone will mix up the order of positional arguments on a function with one argument is… low. Other ways to achieve your goals: Give your functions more descriptive names, as in this name helps me understand what the function does if I didn’t know already. Use a doc string if needed. Give functions a leading underscore to mark them as a private. But consider if you need to do this. You’re not really making someone’s life easier by giving them less tools that are useful. It’s just if you don’t want it to be something supported outside of the scope of that module. __all__ is similar. Have one input type for arguments unless the role of the function is casting/deserialization (single responsibility). It’s fine to have some “helpers” module for stuff that isn’t part of the “main story”. A hint that you’re doing it right is you don’t end up with circular imports there. Check out Grokking Simplicity. I think you’ll like it. You have good instincts, just need to see some ways other people have solved the same problems.
2 of 29
52
There are two questions I think you should ask yourself. Firstly, if these inner functions aren't closing over local variables, what's the benefit compared to putting them outside the function? Outside the function, they're easier to test and to reuse, and perhaps most importantly, to ignore. So I feel like I'd want to get something back in return for that, and it's not clear to me what that is. Secondly, it's worth talking to other people on your team to see what they make of this. I know I've been guilty of writing clever code that seems perfectly intuitive to me but that my teammates stare blankly at. Getting someone else to read it will tell you whether it's readable.
🌐
Python Morsels
pythonmorsels.com › nested-functions
Nested functions in Python - Python Morsels
June 10, 2026 - It's possible in Python to dynamically define a function within another function, and we can even return that inner function so that it can be called later. Nested functions will automatically keep track of the variables that were available in their enclosing scope, that is the variables defined within their outer function.
🌐
Stack Abuse
stackabuse.com › python-nested-functions
Python Nested Functions
December 21, 2018 - Functions are one of the "first-class ... etc. Python supports the concept of a "nested function" or "inner function", which is simply a function defined inside another function....
Find elsewhere
🌐
Analytics Vidhya
analyticsvidhya.com › home › how nested functions are used in python?
How nested functions are used in Python? - Analytics Vidhya
March 4, 2025 - A. A nested function is a function defined within another function. For example, in Python: def outer_function(x): def inner_function(y): return x + y return inner_function Here, inner_function is nested inside outer_function and can access ...
🌐
Colinsblog
colinsblog.net › 2023-08-05-nesting-functions
Better Code Organization by Nesting Functions - Colin's Notes
August 5, 2023 - The inner function has read-only access to its enclosing scope, but isn’t automatically a closure. The inner function accesses the values of the parent scope variables at call time. There’s more you can do with Python inner functions: How Nested Functions are Use in Pytho including making closures.
🌐
Berkeley
pythonnumericalmethods.studentorg.berkeley.edu › notebooks › chapter03.03-Nested-Functions.html
Nested functions — Python Numerical Methods
Once you have created and saved ... and any other function can call on the function as well. A nested function is a function that is defined within another function - parent function....
🌐
Dive into Python
diveintopython.org › home › learn python programming › functions in python › nested functions
Nested Functions in Python - Powerful Tool for Organized Code
May 3, 2024 - Nested functions are functions inside other functions. These functions are particularly useful in programming. They can be used in real-world applications in Python. For instance, a nested function could define a function that calls another function.
🌐
TutorialsPoint
tutorialspoint.com › How-do-nested-functions-work-in-Python
How do nested functions work in Python?
September 28, 2023 - Simply use the def keyword to initialize another function within a function to define a nested function. The following program demonstrates the inner function in Python −
🌐
Flavio Copes
flaviocopes.com › home › python › python nested functions
Python Nested Functions - Flavio Copes
August 7, 2026 - Learn how nested functions work in Python: defining a function inside another to hide local helpers, and using nonlocal to reach the outer variables.
🌐
PrepBytes
prepbytes.com › home › python › python nested functions
Python Nested Functions
March 7, 2023 - Nested function means that you can define a function within another function and use it within the scope of the outer function.
🌐
Programiz
programiz.com › python-programming › closure
Python Closures (With Examples)
Python closure is a nested function that allows us to access variables of the outer function even after the outer function is closed.
🌐
Medium
medium.com › @tanishf24comp › nested-functions-and-their-use-cases-43d799f0de04
Nested Functions and Their Use Cases | by Tanish Fitkariwala | Medium
October 23, 2025 - The utility of nested functions is rooted in how they interact with the enclosing function’s scope — the region of code where a variable is accessible. In Python, the scope resolution follows the LEGB rule: Local $\rightarrow$ Enclosing $\rightarrow$ Global $\rightarrow$ Built-in.
🌐
TestingDocs
testingdocs.com › home › python › python nested functions
Python Nested Functions | TestingDocs
August 8, 2024 - Python supports defining functions inside of a function. A nested function is a function defined inside another function.
🌐
DataCamp
campus.datacamp.com › courses › introduction-to-functions-in-python › default-arguments-variable-length-arguments-and-scope
Nested Functions I | Python
There's nothing new about defining nested functions: you simply define it as you would a regular function with def and embed it inside another function!