nested functions

Python supports nesting one function within another:

    def pnomial(x):
    
        def double(n):
            return 2 * n
    
        return double(x) + 1

tl;dr: Don’t use them.

Their main disadvantages are

  1. testing is too hard, and
  2. namespace coupling brings the gotchas of global variables.

Some folks start nesting functions in an effort to organize the code. Whatever advantage that brings is usually outweighed by the disadvantages. It’s easy to organize code in other ways, such as splitting code into several small modules.


helpers

Prefer to break out a _private helper:

    def _double(n):
       return 2 * n
    
    def pnomial(x):
        return _double(x) + 1

Now when you or someone else wants to write a unit test, it’s easy:

    import unittest
    from .algebra import _double
    
    class TestAlgebra(unittest.TestCase):
        def test_double(self):
            self.assertEqual(6, _double(3))

If a unit test can access it, then other target code can, as well. This can promote code reuse.


coupling

How do nested variables resemble globals? Here’s an illustration.

    def pnomial(x):
    
        def double():
            return 2 * x
    
        return double() + 1

But that’s too automagical, it’s not a clear way to express Author’s Intent.

Occasionally we have a tediously large number of parameters and we do want the helper to be able to conveniently access them without callers repeatedly naming them. And we don’t wish to make them attributes of a new class object.

If that’s the case, clearly articulate your rationale in a one-line # comment , and then nest to your heart’s delight. Otherwise, it’s a feature you should treat with caution.

prev next

Copyright 2023 John Hanley. MIT licensed.