1

While there is a lot of discussion around construction and use of nested functions, there is very little info on when to use them. What I'm trying to find out is: when is it idiomatic to use a nested function? When should you use lambda x: <function> over a nested function?

Python is a language that lets you do a lot of things you shouldn't (ie: using globals). Is this a feature that, while you can use it, you should not?

A scenario I envisioned for using one is in unit testing. Let's say you a method defined like this:

def FunctionOne(varone: int, vartwo: object) -> None:
  assert varone == vartwo() 

vartwo is a function that is passed into the function. Now we want to unittest this. So we write a (partial) unit test that looks like this:

def unittest() -> None:
  def test_function() -> int:
    return 1
  FuncitonOne(1, test_function)

The specifics here are:

  1. The function is only needed in the scope of the unit test function.
  2. The function is never called elsewhere.

Therefore, to summarize: when should you (if ever) use a nested function with Python?

  • a lot of ink on the web have been dedicated to this topic. this is a here's a good read: https://realpython.com/inner-functions-what-are-they-good-for/ – Paul H May 07 '20 at 19:33
  • @PaulH Thanks for this link, it looks like my terminology of "nested functions" might have been a tripping point when researching. –  May 07 '20 at 19:35
  • 1
    The real question is *when should you use a `lambda`*? Pretty much, the only time you should use `lambda` is for any *anonymous function*. And really, that is mostly a matter of *style*. There is nothing that a lambda gives you that isn't available witha full function definition, and there's things that a full function definition can do that lambda cannot. Note, Guido actually wanted to *remove* lambda in the transition from Python 2 to 3. – juanpa.arrivillaga May 07 '20 at 19:51
  • 1
    Now, the only time you should nest a function is if you need to create *a new function* on each invocation of the outer function. This is often the case for higher order functions that return functions, or a function taht takes advantage of a closure created by the nested function. – juanpa.arrivillaga May 07 '20 at 19:53
  • I think the important part to understand is that "nested functions" is really just a case of creating an object inside a function... functions *are just objects*. And you can think of `def foo(...): ...` as syntactic sugar to a call to the `function` class constructor, so `foo = function(...)` This is actually possible, although, you almost never need to invoke the actual function constructor, and it isn't user friendly – juanpa.arrivillaga May 07 '20 at 20:12

1 Answers1

2

First of all, notice that a nested function offers features that a lambda or a global function do not have.

  • It can be multi-statements, by opposition to a lambda
  • It can have a closure, by opposition to a global function

Thus, a purely feature-oriented answer would be to use a nested function whenever you need to define a multi-statements function with a closure.

Here is an example of such a function.

def create_counter(step):
    start = 0
    def count():
        print(start)
        start += step
    return count

Note that another recurring example of that use-case are decorators.

def decorator(f):
    def wrapper(*args):
        ...
        f(*args)
        ...
    return wrapper

@decorator
def my_function(*args):
    ...

Another reason you might want to use a nested function is to make it private in some sense, since the function will then be local and cannot be accessed globally. Although, I see very few cases where this is useful since by choosing proper function names, it should not bother you to have helper functions in your namespace.

Olivier Melançon
  • 21,584
  • 4
  • 41
  • 73