Python functions are first-class citizens. This means that functions have equal status with other objects in Python. Functions can be assigned to variables, stored in collections, created and deleted dynamically, or passed as arguments.
A nested function, also called an inner function, is a function defined inside another function.
#!/usr/bin/python def main(): def build_message(name): msg = f'Hello {name}' return msg name = input("Enter your name: ") msg = build_message(name) print(msg) if __name__ == "__main__": main()The #!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter() 2 is a nested function. It is defined and invoked inside its outer #!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter() 3 function.
A closure is a nested function which has access to a free variable from an enclosing function that has finished its execution. Three characteristics of a Python closure are:
- it is a nested function
- it has access to a free variable in outer scope
- it is returned from the enclosing function
A free variable is a variable that is not bound in the local scope. In order for closures to work with immutable variables such as numbers and strings, we have to use the #!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter() 4 keyword.
Python closures help avoiding the usage of global values and provide some form of data hiding. They are used in Python decorators.
Python simple closure example
The following is a simple example of a Python closure.
#!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter()In the example, we have a #!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter() 5 function, which creates and returns a function. The nested #!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter() 6 function is the closure.
myprinter = make_printer("Hello there")The #!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter() 5 function returns a #!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter() 6 function and assigns it to the #!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter() 9 variable. At this moment, it has finished its execution. However, the #!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter() 6 closure still has access to the myprinter = make_printer("Hello there") 1 variable.
The #!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter() 4 keyword allows us to modify a variable with immutable type in the outer function scope.
#!/usr/bin/python def make_counter(): count = 0 def inner(): nonlocal count count += 1 return count return inner counter = make_counter() c = counter() print(c) c = counter() print(c) c = counter() print(c)The example creates a counter function.
def make_counter(): count = 0 def inner(): nonlocal count count += 1 return count return innerBy using the #!/usr/bin/python def make_printer(msg): msg = "hi there" def printer(): print(msg) return printer myprinter = make_printer("Hello there") myprinter() myprinter() myprinter() 4 keyword, the myprinter = make_printer("Hello there") 4 variable becomes a free variable. Now we can modify it.