How do you call an inner function from the outside function in python?

Nonlocal variable in a nested function

Before getting into what a closure is, we have to first understand what a nested function and nonlocal variable is.

A function defined inside another function is called a nested function. Nested functions can access variables of the enclosing scope.

In Python, these non-local variables are read-only by default and we must declare them explicitly as non-local [using nonlocal keyword] in order to modify them.

Following is an example of a nested function accessing a non-local variable.

def print_msg[msg]:
    # This is the outer enclosing function

    def printer[]:
        # This is the nested function
        print[msg]

    printer[]

# We execute the function
# Output: Hello
print_msg["Hello"]

Output

Hello

We can see that the nested printer[] function was able to access the non-local msg variable of the enclosing function.

Defining a Closure Function

In the example above, what would happen if the last line of the function print_msg[] returned the printer[] function instead of calling it? This means the function was defined as follows:

def print_msg[msg]:
    # This is the outer enclosing function

    def printer[]:
        # This is the nested function
        print[msg]

    return printer  # returns the nested function


# Now let's try calling this function.
# Output: Hello
another = print_msg["Hello"]
another[]

Output

Hello

That's unusual.

The print_msg[] function was called with the string "Hello" and the returned function was bound to the name another. On calling another[], the message was still remembered although we had already finished executing the print_msg[] function.

This technique by which some data ["Hello in this case] gets attached to the code is called closure in Python.

This value in the enclosing scope is remembered even when the variable goes out of scope or the function itself is removed from the current namespace.

Try running the following in the Python shell to see the output.

>>> del print_msg
>>> another[]
Hello
>>> print_msg["Hello"]
Traceback [most recent call last]:
...
NameError: name 'print_msg' is not defined

Here, the returned function still works even when the original function was deleted.

When do we have closures?

As seen from the above example, we have a closure in Python when a nested function references a value in its enclosing scope.

The criteria that must be met to create closure in Python are summarized in the following points.

  • We must have a nested function [function inside a function].
  • The nested function must refer to a value defined in the enclosing function.
  • The enclosing function must return the nested function.

When to use closures?

So what are closures good for?

Closures can avoid the use of global values and provides some form of data hiding. It can also provide an object oriented solution to the problem.

When there are few methods [one method in most cases] to be implemented in a class, closures can provide an alternate and more elegant solution. But when the number of attributes and methods get larger, it's better to implement a class.

Here is a simple example where a closure might be more preferable than defining a class and making objects. But the preference is all yours.

def make_multiplier_of[n]:
    def multiplier[x]:
        return x * n
    return multiplier


# Multiplier of 3
times3 = make_multiplier_of[3]

# Multiplier of 5
times5 = make_multiplier_of[5]

# Output: 27
print[times3[9]]

# Output: 15
print[times5[3]]

# Output: 30
print[times5[times3[2]]]

Output

27
15
30

Python Decorators make an extensive use of closures as well.

On a concluding note, it is good to point out that the values that get enclosed in the closure function can be found out.

All function objects have a __closure__ attribute that returns a tuple of cell objects if it is a closure function. Referring to the example above, we know times3 and times5 are closure functions.

>>> make_multiplier_of.__closure__
>>> times3.__closure__
[,]

The cell object has the attribute cell_contents which stores the closed value.

>>> times3.__closure__[0].cell_contents
3
>>> times5.__closure__[0].cell_contents
5

Python offers many features and one such feature is that it has the ability to implement Inner Function or Nested Functions. In Simple terms, You can define a Function within another Function. Let’s Learn about Python Inner Function / Nested Function.

Python Inner Function

def outerFunction[a, b]:
    def innerFunction[c, d]:
        return c*d
    return innerFunction[a, b]

Enter fullscreen mode Exit fullscreen mode

print[outerFunction[10, 20]]
Output:
200

Enter fullscreen mode Exit fullscreen mode

In the above code, the outer function is called with two integer arguments and the outer function has an inner function that calls and returns the inner function with the arguments of the outer function.

This feature in Python helps us to encapsulate the function.

If you try to call the inner function from the outside scope of outer function.

Calling Inner Function.

def outerFunction[a, b]:
    def innerFunction[c, d]:
        return c*d
    return innerFunction[a, b]


print[innerFunction[10, 20]]
Error:
Traceback [most recent call last]:
  File ".\sr.py", line 7, in 
    print[innerFunction[10, 20]]
NameError: name 'innerFunction' is not defined

Enter fullscreen mode Exit fullscreen mode

Thus we can conclude that the inner function is encapsulated from global scope.

DRY Principle [Don’t Repeat Yourself]

The Inner Function Feature also helps us to avoid the code duplication and follows the DRY principle.

def wish[name]:
    def say[Quote]:
        return f"Good Morning, {name}"
    return say[name]


print[wish["HTD"]]
Output:
Good Morning, HTD

Enter fullscreen mode Exit fullscreen mode

Inner Function Scope In Python

Python Inner Functions or Nested Functions can access the variables of the outer function as well as the global variables.

text = "Hey"


def wish[]:
    name = "HTD"

    def say[]:
        quote = "Good Morning"
        return f"{text} {quote}, {name}"
    return say[]


print[wish[]]
Output:
Hey Good Morning, HTD

Enter fullscreen mode Exit fullscreen mode

The inner functions variable has a local scope that is limited only to that function. Inner Functions variables can’t be accessed at the outer function scope.

Learn more from the original post: Python Inner Function

How do you call a function inside another function in Python?

Defining an Inner Function To call function2[] , we must first call function1[] . The function1[] will then go ahead and call function2[] as it has been defined inside it. The code will return nothing when executed! The code returns the multiplication of the two numbers, that is, 10 and 5.

How do you call a nested function outside a main function in Python?

There are two main ways to solve this, but both involve modifying a :.
The global keyword [not recommended] def a[]: global b def b[]: print["hi"] ... .
Returning the function from a and passing it to c def a[]: def b[]: print["hi"] return b def c[b]: #your code..

Can you call a nested function outside a function?

Nested function is private to containing function Only the containing function can access the nested function. We cannot access it anywhere outside the function. This is because the inner function is defined in the scope of the outer function [or containing function].

How do you call a function outside Python?

Create a program to understand Python functions as an object. def MyObject[text]: # Pass an argument. # Call the function inside the print[] function. # call the function using the str variable.

Bài mới nhất

Chủ Đề