Python Inner Functions - GeeksforGeeks

25 Nov, 2019
In Python, functions are treated as first class objects. First class objects in a language are handled uniformly throughout. They may be stored in data structures, passed as arguments, or used in control structures. A programming language is said to support first-class functions if it treats functions as first-class objects. Python supports the concept of First Class functions.
Properties of first class functions:
A function is an instance of the Object type.
You can store the function in a variable.
You can pass the function as a parameter to another function.
You can return the function from a function.
You can store them in data structures such as hash tables, lists, ...
Note: To know more about first class objects click here.
A function which is defined inside another function is known as inner function or nested function. Nested functions are able to access variables of the enclosing scope. Inner functions are used so that they can be protected from everything happening outside the function. This process is also known as Encapsulation. To know more about encapsulation click here.
Example:
# Python program to illustrate # nested functions def outerFunction(text):     text = text         def innerFunction():         print(text)         innerFunction()     if __name__ == '__main__':     outerFunction('Hey !') 
Output:
Hey!

In the above example, innerFunction() has been defined inside outerFunction(), making it an inner function. To call innerFunction(), we must first call outerFunction(). The outerFunction() will then go ahead and call innerFunction() as it has been defined inside it.
It is important that outer function has to be called, so that the inner function can execute. To demonstrate this consider the below example:Example:
# Python program to illustrate # nested functions def outerFunction(text):     text = text         def innerFunction():         print(text)         innerFunction() 
Output:
This code will return nothing when executed.

The location where we can find a variable and also access it if required is called the scope of a variable.It is known how to access a global variable inside a function, but, what about accessing the variable of an outer function? Let’s see an example:
# Python program to # demonstrate accessing of# variables of nested functions  def f1():    s = 'I love GeeksforGeeks'          def f2():        print(s)              f2()  # Driver's codef1()
Output:
I love GeeksforGeeks

In the above example, it can be seen that it is similar to accessing the global variable from a function. Now let’s suppose you want to change the variable of the outer function.
# Python program to # demonstrate accessing of# variables of nested functions  def f1():    s = 'I love GeeksforGeeks'          def f2():        s = 'Me too'        print(s)              f2()    print(s)  # Driver's codef1()
Output:
Me too
I love GeeksforGeeks

It can be seen the value of the variable of the outer function is not changed. However, the value of the variable of the outer function can be changed. There are different ways to change the value of the variable of the outer function.
Using an iterable –# Python program to # demonstrate accessing of# variables of nested functions  def f1():    s = ['I love GeeksforGeeks']          def f2():        s[0] = 'Me too'        print(s)              f2()    print(s)  # Driver's codef1()Output:['Me too']
['Me too']

# Python program to # demonstrate accessing of# variables of nested functions  def f1():    s = ['I love GeeksforGeeks']          def f2():        s[0] = 'Me too'        print(s)              f2()    print(s)  # Driver's codef1()
Output:
['Me too']
['Me too']

Using nonlocal keyword –# Python program to # demonstrate accessing of# variables of nested functions  def f1():    s = 'I love GeeksforGeeks'          def f2():        nonlocal s        s = 'Me too'        print(s)              f2()    print(s)  # Driver's codef1()Output:Me too
Me too

# Python program to # demonstrate accessing of# variables of nested functions  def f1():    s = 'I love GeeksforGeeks'          def f2():        nonlocal s        s = 'Me too'        print(s)              f2()    print(s)  # Driver's codef1()
Output:
Me too
Me too

Value can also be changed as shown in the below example.# Python program to # demonstrate accessing of# variables of nested functions  def f1():    f1.s = 'I love GeeksforGeeks'          def f2():        f1.s = 'Me too'        print(f1.s)              f2()    print(f1.s)  # Driver's codef1()Output:Me too
Me too

# Python program to # demonstrate accessing of# variables of nested functions  def f1():    f1.s = 'I love GeeksforGeeks'          def f2():        f1.s = 'Me too'        print(f1.s)              f2()    print(f1.s)  # Driver's codef1()
Output:
Me too
Me too

A Closure is a function object that remembers values in enclosing scopes even if they are not present in memory.
It is a record that stores a function together with an environment: a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created.
A closure—unlike a plain function—allows the function to access those captured variables through the closure’s copies of their values or references, even when the function is invoked outside their scope.filter_none.
# Python program to illustrate # closures def outerFunction(text):     text = text         def innerFunction():         print(text)         return innerFunction # Note we are returning function WITHOUT parenthesis     if __name__ == '__main__':     myFunction = outerFunction('Hey !')     myFunction() 
Output:
Hey!

As observed from above code, closures help to invoke function outside their scope.
The function innerFunction has its scope only inside the outerFunction. But with the use of closures we can easily extend its scope to invoke a function outside its scope.
# Python program to illustrate # closures import logging logging.basicConfig(filename ='example.log', level = logging.INFO)         def logger(func):     def log_func(*args):         logging.info(             'Running "{}" with arguments {}'.format(func.__name__, args))         print(func(*args))     # Necessary for closure to work (returning WITHOUT parenthesis)     return log_func                   def add(x, y):     return x + y     def sub(x, y):     return x-y     add_logger = logger(add) sub_logger = logger(sub)     add_logger(3, 3) add_logger(4, 5)     sub_logger(10, 5) sub_logger(20, 10) 
Output:
6
9
5
10

Python-Functions
Python
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Python Dictionary
Read a file line by line in Python
How to Install PIP on Windows ?
Enumerate() in Python
Iterate over a list in Python
Different ways to create Pandas Dataframe
Python String | replace()
Python program to convert a list to string
Create a Pandas DataFrame from Lists
Reading and Writing to text files in Python