11

I have seen some code that has these structures.

Structure 1: An internal function is created within a function

def external_func(num):
    def internal_func(num2):
        return num2*2
    return internal_func(num + 10)


test = external_func(5)
print(test)

Structure 2: A function is calling another function that is outside itself.

def _internal_func2(num2):
    return num2 * 2

def external_func2(num):
    return _internal_func2(num + 10)

test2 = external_func2(5)
print(test2)

For this particular case, both functions provide the same output. Where and why should I use each one of these structures?

1 Answer 1

14

One of the main benefits of Structure 1 is that it makes internal_func locally scoped to external_func. You are making it clear that internal_func should be accessed only by external_func. Treat it just like any other regular variable that was defined inside external_func. Similar to not having global variables scattered about, sometimes you want to "hide" an implementation inside other functions.

You can then have other similarly named internal_func's in other methods and their names won't clash:

In [39]: def external_func_x2(num):
    ...:     def f():
    ...:         return num * 2
    ...:     return f
    ...: 

In [40]: def external_func_x3(num):
    ...:     def f():
    ...:         return num * 3
    ...:     return f

One common purpose is to make functions that generate other functions based on certain conditions:

In [44]: def make_multiplier(mult):
    ...:     def f(num):
    ...:         return num*mult
    ...:     return f
    ...: 

In [45]: x4 = make_multiplier(4)

In [46]: x4(8)
Out[46]: 32

In [47]: x3 = make_multiplier(3)

In [48]: x3(8)
Out[48]: 24

You could do the same examples above with Structure 2 (or with functools.partial) but then it will be less readable, and you'll need to expose this inner f function in the outer scope/namespace, even though it's only used by the make_multiplier method. You'll also have to pass arguments around from one function to another, instead of having a closure like what we have with Structure 1.

If you are making this make_multiplier as part of some library/API, using Structure 1 "hides" this f function and makes it a bit clearer and more readable to clients/users of the library/API that they only need to "see" the make_multiplier method.

There is also an argument for maintainability. If you need to modify make_multiplier, it's already obvious that you need to modify f, and you can be pretty sure that modifying f will not break other parts of your code, since no one uses it other than make_multiplier.

Structure 2 is your standard good practice of "splitting your big functions into smaller more manageable and reusable functions". Its main advantages over Structure 1 are testability and reusability. It is much easier to test and mock out _internal_func2 directly, without needing to call external_func2, which is great if external_func2 is especially complicated in itself to call. It would also be very difficult to write tests that directly target a nested inner function.

It also makes _internal_func2 reusable by other methods. Comparing it to the example above for Structure 1, if you find yourself writing the same inner f nested inside many external_func's, then it's probably better to move that out and convert to Structure 2 style.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.