def init():
'''
:return: increment_num function
'''
num = 0
def increment_num():
'''
increments a number by one each call
:return: num + 1
'''
nonlocal num
num += 1
return num
return increment_num
increment = init()
print(increment())
print(increment())
# output 1 2
# Closure in Python. Criteria include
# 1. must have a nested function
# 2. nested function must refer to a value defined in the enclosing outer function
# 3. enclosing function must return a reference of nested function
# consequence: the variable in the enclosing scope is remembered even when the
# variable goes out of scope or the function itself is removed from the current namespace.
# Illustration
def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment # return reference to inner function
instance = counter() # counter() function is out of namespace after this line
print(instance()) # but counter() function's inner function still works
print(instance()) # and count variable doesn't get refreshed to 0
print(instance())
# 1
# 2
# 3
# Pros: Closures can avoid the use of global values and provides some form of data hiding.
# When there is one method to be implemented in a class, closures can provide an
# alternate and more elegant solution.
def make_multiplier_of(n):
def multiplier(x):
return x * n
return multiplier
times3 = make_multiplier_of(3) # Multiplier of 3
times5 = make_multiplier_of(5) # Multiplier of 5
print(times3(9))
# Output: 27
print(times5(3))
# Output: 15
print(times5(times3(2)))
# Output: 30
def make_counter():
count = 0
def inner():
nonlocal count
count += 1
return count
return inner
def make_summer():
data = []
def summer(val):
data.append(val)
_sum = sum(data)
return _sum
return summer
# Closure in Python. Criteria include
# 1. must have a nested function
# 2. nested function must refer to a value defined in the enclosing outer function
# 3. enclosing function must return a reference of nested function
# consequence: inner function that remembers the variables in its enclosing scope
# even when the outer function is done executing, the variable goes out of scope
# or the function itself is removed from the current namespace.
# Illustration
def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment # return reference to inner function
instance = counter() # counter() function is removed from namespace after this line
print(instance()) # but counter() function's inner function still works
print(instance()) # and it remembers count variable, i.e. it does not get refreshed to 0
print(instance())
# 1
# 2
# 3
# Pros: Closures can avoid the use of global values and provides some form of data hiding.
# When there is one method to be implemented in a class, closures can provide an
# alternate and more elegant solution.
def make_multiplier_of(n):
def multiplier(x):
return x * n
return multiplier
times3 = make_multiplier_of(3) # Multiplier of 3
times5 = make_multiplier_of(5) # Multiplier of 5
print(times3(9))
# Output: 27
print(times5(3))
# Output: 15
print(times5(times3(2)))
# Output: 30
# Python decorators use closure extensively, as it takes a function as parameter
# adds functionality to it and returns the original function.