How to Nest Functions in Parent Functions in Python
In the last guide, we walked through the key differences between returning a value from a function versus simply printing a value out, and we walked through the full name and greeting example.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
  • Complete the Exercise
Video locked
This video is viewable to users with a Bottega Bootcamp license

In this guide, we are going to extend that knowledge and we're going to talk about nested functions. And so Python is different than many other programming languages where it allows you to place one function inside of another function that is not something that all programming languages allow for.

But python does and it can lead to some very interesting looking code but it can also be very helpful when implemented properly. I've kept our two functions of full_name and greeting here in our code file.

def full_name(first, last):
    return f'{first} {last}'

Kristine = full_name('Kristine', 'Hudgens')

def greeting(name):
  print(f'Hi {name}!')


greeting('Kristine', 'Hudgens')

The reason is that we're going to use this identical code to be able to refactor it and place our full name function inside of our greeting function. And so we're not going to have to recreate a lot instead we're going to reorganize it so that it can be used the way that we need it to be. So we're no longer going to be calling full_name the way we did right here.

Kristine = full_name('Kristine', 'Hudgens')

So we can delete that code and I'm going to take this full_name function here and I'm going to cut it and place it inside of this greeting function. Now you have to be very careful to make sure that you nest inside and that you have the correct indentation for both functions. So this will throw an error because even though our full name function is nested properly our return statement isn't. So if you indent that then that is going to properly work now or at least it's going to work for this one function.

def greeting(name):
  def full_name(first, last):
    return f'{first} {last}'

So we've taken our greeting function and now we've nested full name inside of this.

Now, what do we have to do? Well, we have this function but we don't need everything inside of it anymore. And the reason is that full_name, because it's nested inside of greeting does not need to have these arguments we can just call full_name with no arguments and we're going to treat greeting as the parent function here. And so it needs to have different function arguments so we're going to say first and last and so now we're going to pass in two arguments whenever we call greeting and this full_name function is going to have access to first and last and so this is going to actually make for more efficient code and I think more readable in this sense.

So if we have full_name here and then we have first and last and these values are returned so this formatted string is going to get returned inside of our print statement here. We no longer call name, now we call our full name function so we're going to call it make sure that you include the parentheses at the end. I'm going to add one more line here just so it's easier to read and it's very clear that full_name is its own function it simply nested inside of greeting and everything else looks right. This is all we need to do to have the entire system work.

def greeting(first, last):
  def full_name():
    return f'{first} {last}'

Now when we come down to greeting we're no longer going to be just passing in a variable as we did before. Now we're going to pass in a first name and a last name so I'm going to pass in these values and if I run this you can see that everything functions just like before.

large

Now the most common question that is asked whenever you're working with nested function is when should you choose to nest versus keep them separate. And one of my rules of thumb for it is whenever I have a function that does not need to exist outside of a parent function then that is a good time to perform nesting.

So for example, if you never need to call this full_name function except in the context of greeting so greeting is the only function that calls the values here. Then there is no reason for this full_name function to be in a different part of the application you can nested inside and then call it whenever you need to.

However, if some other part of the program does need access to the full name function then you may want to keep it separate and call them independent of each other. That's my personal rule of thumb when it comes to choosing when and when not to nest functions in Python.

Code

def greeting(first, last):
  def full_name():
    return f'{first} {last}'

  print(f'Hi {full_name()}!')


greeting('Kristine', 'Hudgens')