Python

Python closure

In this article, we are going to discuss python closure.Before understanding python closure, we need to understand nested functions and non-local variables.

Nested function:

A nested function is defined inside another function. These functions can access a variable of the outside function. The non-local variable we can access within their scope.

Ex:

defouter_fun(s):
    msg = s #non local variable
definner_fun():
print(msg)
inner_fun()

outer_fun('Good morning')

Output:

F:\python_Coarse\closure_screenshots\1.png

In the above example, the inner_fun is a nested function, and msg is a non-local variable. We can access these inside the outer_fun body.

Closure Definition:

Python closure is a nested function. We can access the variable outside the scope. This concept is essential for understanding python decorators.

All nested functions are not closures. The following three criteria should meet to define a closure:

  1. We should have a nested function(function inside another function)
  2. The nested function should refer to a variable nonlocal to it
  3. The outer scope function must return the inner function.

Ex:

#defining nested functions
defgreet_msg(s):
    msg = s# msg is having scope in outer function
defprint_msg():
print(msg)#using non local variable
returnprint_msg#return object instead of calling a inner function

call_fun=greet_msg('Good morning')
call_fun()
call_fun()

Output:

F:\python_Coarse\closure_screenshots\2.png

In the above example, the greet_msg is the outer function. This creates an inner function (greet_msg is closure here), and it is returned.

The outer function greet_msg returns a print_msg function, and it is assigned to the call_fun variable. Here we see the outer function finished its execution, but we can still access the msg variable.

How to modify variable inside the Closure:

Using nonlocal keyword we can modify the variable inside the inner function.

Ex: Without using nonlocal keyword. Here we are trying to modify the num variable inside closure and got unboundLocalError because python thinks num as a local variable and num is not defined inside fun().

defgenerate_num():
    num =0
deffun():
        num +=1
print(num)
return fun
g =generate_num()
g()
g()
g()

Output:

F:\python_Coarse\closure_screenshots\3.png

Ex: With using nonlocal keyword. In the below example using nonlocal keyword we will be able to modify the num variable.

defgenerate_num():
    num =0
deffun():
nonlocal num
        num +=1
print(num)
return fun
g =generate_num()
g()
g()
g()

Output:

F:\python_Coarse\closure_screenshots\4.png

We will write more example using a closure:

Ex: This will print passed arguments and function name

defouter(func):
defclosure(*args):
print('Running "{}" with arguments {}'.format(func.__name__, args))
print(func(*args))
return closure

defadd(a, b):
returna+b

defsub(a, b):
return a-b

defmul(a, b):
return a*b

defdiv(a, b):
return a/b

add_closure= outer(add)
sub_closure= outer(sub)

mul_closure= outer(mul)
div_closure= outer(div)

add_closure(3, 3)
add_closure(4, 5)

sub_closure(10, 5)
sub_closure(20, 10)

mul_closure(10, 5)
mul_closure(20, 10)

div_closure(10, 5)
div_closure(20, 10)

Output:

F:\python_Coarse\closure_screenshots\5.png

Ex: In the below example, each time the closure is called, the values will be appended to a list and it will add all the values in list then return a value.

defaddition():
    res = []
deffunc_sum(val):
res.append(val)
sum_res=sum(res)
returnsum_res
returnfunc_sum

s =addition()

t =s(2)
print(t)

t =s(5)
print(t)

t =s(10)
print(t)

t =s(100)
print(t)

Output:

F:\python_Coarse\closure_screenshots\6.png

Ex: In this example multiply the inner function parameter number by outer function parameter
def multiply_by_number(m):

# inner function
defoperation(n):
# m is multiplied  by n
return n * m
# return inner function
return operation

multiply_by_10 =multiply_by_number(10)

# should print 20
print(multiply_by_10(2))
# should print 100
print(multiply_by_10(10))
# should print 120
print(multiply_by_10(12))

Output:

F:\python_Coarse\closure_screenshots\7.png

Conclusion:

Python closure is a nested function. With this, we can avoid using global variables using non-local variables. This provides some data hiding and understanding this concept helpful in building a python decorator.

About the author

Bamdeb Ghosh

Bamdeb Ghosh is having hands-on experience in Wireless networking domain.He's an expert in Wireshark capture analysis on Wireless or Wired Networking along with knowledge of Android, Bluetooth, Linux commands and python. Follow his site: wifisharks.com