There are a lot of good reasons. Personally, I often use nested functions to keep the namespace clean. It's especially useful within object methods :

class Foo(object):
    def bar(self):
        def baz(val):
            return val
        return [ baz(i) for i in range(1,101) ]

If I declare baz outside of bar, I either need to make it a method of Foo, or expose it to the entire package.

Answer from Jonathan Vanasco on Stack Overflow
🌐
Reddit
reddit.com › r/python › is nesting function declarations bad practice?
r/Python on Reddit: Is nesting function declarations bad practice?
May 27, 2021 -

Today on a PR I saw several functions defined within an str function, and I noted that that should be changed to meet best practices/pep8.

The submitter argued that it wasn't an issue, and sure enough I checked the pep8 and couldn't find a reference to it.

I could've sworn that nesting function declarations is looked down upon/bad practice in Python; am I right or am I just misremembering?

🌐
Medium
medium.com › re-stacked › are-python-nested-function-calls-a-bad-practice-35aa133af7e4
Are Python nested function calls a bad practice? | by Kyle Pastor | RE:Stacked | Medium
February 21, 2023 - Nested function calls are not inherently bad practice in Python or in programming in general. In fact, nested function calls can often make code more concise and easier to read.
Top answer
1 of 5
17

This really depends on how much nesting you use. After all, you are allowed to use function results directly in expressions to improve readability. Both, code that does not use nested expressions (like assembler code), and code that uses too much nested expressions is hard to read. Good code tries to strike a balance in between the extremes.

So lets look at some examples. The one you gave in your question seems quite legit to me, so nothing to worry here. However, a line like

foo(bar(baz(moo, fab), bim(bam(ext, rel, woot, baz(moo, fab)), noob), bom, zak(bif)));

would definitely not be tolerable. Likewise, code like

double xsquare = x*x;
double ysquare = y*y;
double zsquare = z*z;
double xysquare = xsquare + ysquare;
double xyzsquare = xysquare + zsquare;
double length = sqrt(xyzsquare);

would not be very readable as well. sqrt(x*x + y*y + z*z) is much easier to understand, even though it combines a total of six different operation in one expression.

My advice is to pay attention to what expressions you can still parse in your head easily. The moment you need to take a second look to grasp what a single expression does, it's time to introduce an additional variable.

2 of 5
10

The concept underlying your question is so important I feel it needs another answer rather than just a comment (as I had started to do).

The other 3 answers thus far provide some useful points of consideration on whether a given situation merits using what you call "nested function calls". But perhaps a more important point is hidden in the comments under your question: in case you missed the subtlety in what those erudite folks are suggesting, Carl, you have discovered for yourself the topic actually called functional programming. If you have never seen the term, you might not have thought it was really a "thing" in @HighPerformanceMark's comment.

But indeed it is! Functional programming has been written about for decades, since John Hughes' seminal paper Why Functional Programming Matters. There are some languages that are functional languages (i.e. they only let you write in a functional programming style), languages like Erlang, Lisp, OCaml, or Haskell. But there are many more languages that are hybrid imperative/functional languages. That is, they are traditionally imperative languages but offer some support for functional programming as well, including Perl, C++, Java, C#, and many more. Wikipedia's entry on functional programming provides a nice section showing a comparison of functional style vs. imperative style for a number of languages.

There is much to say on the differences between imperative and functional styles, but the key starting point is that with functional programming, functions or methods have no side effects, making it in general easier to both understand and debug programs.

For further reading, you might also take a look at Reginald Braithwaite's Why "Why Functional Programming Matters" Matters and another interesting post here on SO, Why functional languages?

🌐
Reddit
reddit.com › r/learnpython › when not to use nested functions?
r/learnpython on Reddit: When not to use nested functions?
November 28, 2019 -

I may be calling this wrong, but all I mean is:

def func1():
    
    def func2():

I've seen posts explaining when you should use this, but I haven't found much against using it. I seem to be unintentionally using quite a few.

Is using a nested function best practice? Is it 'efficient'?

 

I only ask as my code seems to be running a little slow at the beginning, so trying to see if I can improve that

🌐
Colinsblog
colinsblog.net › 2023-08-05-nesting-functions
Better Code Organization by Nesting Functions - Colin's Notes
August 5, 2023 - In either case function nesting can be a useful way to structure code and document behavior regardless of state if your language allows it. Also, whether or not a language supports first-class functions (passing functions as values) you can still use nesting as an organization tool.
🌐
Reddit
reddit.com › r/learnpython › is it bad practice to have functions nested in your main function?
r/learnpython on Reddit: Is it bad practice to have functions nested in your main function?
June 11, 2023 -

So, I am writing a main function (so that I can say if name == "main" because that is good practice). And my main file accesses a lot of classes that are not inside of the main function. This is all fine, but then there is a function in a number of different classes that I want to call at once. Think of it like: reset_box(), reset_circle(), reset_triangle() or whatever.

Under certain conditions I want to just hit all these at once. So, it would be nice to have a function I can call that just does them all at once rather than writing them all out each time.

It would be easiest to do this in the main function, to just add in another function that resets everything. Or is this bad code? Should I take the function out of main and call it that way? The downside of this is that I have to pass it every object that I want to reset which will make it look a little ugly?

What are people's thoughts? Is it better to have a little function inside main that I can call to reset a bunch of objects. Or does it seem better to have the function out of main and just pass in every object that I need to?

Top answer
1 of 9
40
You can just make a function that calls all of them def all(): class.method_1() class_two.method_2() class.method_3() Then when you want to cal all three at once you you just call “all()” generally the rule of thumb is if you have to do something more then twice it should probably be it’s own function. We cal this DRY Don’t Repeat Yourself code as opposed to WET We Enjoy Typing code. We are going to need some code to really understand you problem. main() should be calling everything as usually it’s the only thing that is actually running.
2 of 9
4
I'm not a Python programmer per se, I spend more time with C so I may be missing something, but I think that in languages that support it it is NOT a bad practice (at all) to define functions within the scope where they are used. It's a form of encapsulation, and it can serve as a way to keep your code organised and tidy. If your inner function is never called outside of the main function, it makes sense to define it within that main function - making it invisible to anything else. But if I were building something in Python I think I would go one step (OK, a few steps) further and implement the whole application in a class. Then I could just do something like this: if __name__ == "__main__": application = Application() application.run() Of course, any methods of the Application class could also have nested functions within them. You can take this as far as you like. In any case I don't think you really need a function called main(), that's just a leftover convention from C. In Python, anything after if __name__ == "__main__": could be considered the "main" part of your program.
🌐
Towards Data Science
towardsdatascience.com › home › programming › should you use nested functions to encapsulate logic?
Should you use nested functions to encapsulate logic? | Towards Data Science
November 17, 2020 - E.g. we mark functions as private ... (well in python we can't really, so we use a leading underscore convention _like_this). So that's a good reason to use nested functions - help the reader understand that the logic of bar will not be used anywhere else. Learn this step by step with the interactive Computer Science roadmap. However beyond considering the benefits of something, we should also consider the cost. So what are the costs ...
🌐
Reddit
reddit.com › r/learnprogramming › nested function best practices (python)
r/learnprogramming on Reddit: Nested Function Best Practices (Python)
April 24, 2019 -

I have been writing a class which resembles a binary tree and have been looking to clean up my code a bit and found my way to nested functions. I understand the basic logic behind them and what not, my question is more on how they are used within custom objects.

For example, if i am trying to print the tree in-order and i do something like:

def print_inorder(self):
    def display(node, level):
        if not node:
            return 
        display(node.left_child, level + 1)
        print('\t' * level, node)
        display(node.right_child, level + 1)
   display(self.root, 0)

Would this be correct best practices? The thing that is somewhat confusing to me is switching from using 'self.' for functions relating to the object, to an inner function that doesn't need a 'self.' even though an object is technically calling it. is this already best practice or should I still be using the 'self.'? or is there a better convention to use all together? Thanks.

Find elsewhere
🌐
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 › learnprogramming › comments › 91bnk8 › python_should_i_use_nested_functions_for_this
r/learnprogramming - [Python] Should I use nested functions for this?
July 24, 2018 -

I have two functions: X and Y.

Y is a somewhat big function that calls X multiple times.

X is only called by Y.

Should I nest the definition of X inside of Y? Or should I leave it out?

Note: I define X as a function because it encapsulates multiple lines of code and I don't want a lot of duplicated code inside Y.

Top answer
1 of 12
137
>>> def sum(x, y):
...     def do_it():
...             return x + y
...     return do_it
... 
>>> a = sum(1, 3)
>>> a
<function do_it at 0xb772b304>
>>> a()
4

Is this what you were looking for? It's called a closure.

2 of 12
57

You don't really gain much by doing this, in fact it slows method_a down because it'll define and recompile the other function every time it's called. Given that, it would probably be better to just prefix the function name with underscore to indicate it's a private method -- i.e. _method_b.

I suppose you might want to do this if the nested function's definition varied each time for some reason, but that may indicate a flaw in your design. That said, there is a valid reason to do this to allow the nested function to use arguments that were passed to the outer function but not explicitly passed on to them, which sometimes occurs when writing function decorators, for example. It's what is being shown in the accepted answer although a decorator is not being defined or used.

Update:

Here's proof that nesting them is slower (using Python 3.6.1), although admittedly not by much in this trivial case:

setup = """
class Test(object):
    def separate(self, arg):
        some_data = self._method_b(arg)

    def _method_b(self, arg):
        return arg+1

    def nested(self, arg):

        def method_b2(self, arg):
            return arg+1

        some_data = method_b2(self, arg)

obj = Test()
"""
from timeit import Timer
print(min(Timer(stmt='obj.separate(42)', setup=setup).repeat()))  # -> 0.24479823284461724
print(min(Timer(stmt='obj.nested(42)', setup=setup).repeat()))    # -> 0.26553459700452575

Note I added some self arguments to your sample functions to make them more like real methods (although method_b2 still isn't technically a method of the Test class). Also the nested function is actually called in that version, unlike yours.

🌐
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.org
discuss.python.org › python help
The cost of nested definitions - Python Help - Discussions on Python.org
August 7, 2023 - My problem is advanced and out of the scope of the question. So I’ll keep it simple. Imagine the following: This is a set of helper functions, they only serve to make other functions more readable. def functionA(*args, **kwargs): ... def functionB(*args, **kwargs): ... def functionC(*args, **kwargs): ... But then I have my main functions: def mainA(*args, **kwargs): ... a = functionA(*args, **kwargs) ... def mainB(*args, **kwargs): ....
🌐
Analytics Vidhya
analyticsvidhya.com › home › how nested functions are used in python?
How nested functions are used in Python? - Analytics Vidhya
March 4, 2025 - Python functions in their rights are equal to any other objects, such as numbers, strings, lists, tuples, modules, etc. That is, they can be dynamically created or destroyed, stored in data structures, passed as arguments to other functions, used as returned values. If we do not need to hide the internal functions from the outside world, then there is no particular reason for nesting.