An example of a method in python that USES the closure Closure function as a return value

  • 2020-06-15 09:46:20
  • OfStack

preface

First, consider the concept of closures: Closures (Closure) are short for lexical closures (Lexical Closure), functions that refer to free variables. The referenced free variable will exist with the function 1, even if it has left the environment in which it was created. So, closures are entities composed of functions and their associated reference environments.

1. Function as return value

In addition to taking functions as arguments, higher-order functions can also return functions as result values.


>>> def lazy_sum(*args):
...  def sum():
...   ax = 0
...   for n in args:
...    ax = ax + n
...   return ax
...  return sum
... 
>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
<function lazy_sum.<locals>.sum at 0x1014ae730>
>>> f()
25

When we call lazy_sum(), each call returns a new function, even though the same arguments are passed in:


>>> f1 = lazy_sum(1, 3, 5, 7)
>>> f2 = lazy_sum(1, 3, 5, 7)
>>> f1
<function lazy_sum.<locals>.sum at 0x1014ae8c8>
>>> f2
<function lazy_sum.<locals>.sum at 0x1014ae7b8>
>>> f1 == f2
False

2. The closure

In computer science, closures (Closure) are short for lexical closures (Lexical Closure), functions that refer to free variables. The referenced free variable will exist with the function 1, even if it has left the environment in which it was created. So, there is another way of saying that closures are entities composed of functions and their associated reference environments. Closures can have multiple instances at run time, and different reference environments and the same combination of functions can produce different instances.

Simply put, such an internal function can use the behavior of an external function variable, called a closure.

In this case, the function sum is defined in the function lazy_sum, and the inner function sum can refer to the arguments and local variables of the outer function lazy_sum. When lazy_sum returns sum, the associated arguments and variables are stored in the returned function, which is a very powerful structure called a "closure".

Note that the returned function refers to the local variable args within its definition, so when a function returns a function, its internal local variable is also referred to by the new function. Therefore, closure is easy to use and not easy to implement.

Keep one thing in mind when returning closures: Return functions do not refer to any circular variables, or variables that change later.


>>> def count():
...  fs = []
...  for i in range(1, 4):
...   def f():
...    return i * i
...   fs.append(f)
...  return fs
... 
>>> f1, f2, f3 = count()
>>> f1()
9
>>> f2()
9
>>> f3()
9

It's all nine! The reason is that the returned function references the loop variable i, but it does not execute immediately. By the time all three functions return, the variable they referenced, i, has become 3, so the final result is 9.

What if 1 must refer to a loop variable? The method is to create another function that USES the parameter of the function to bind the current value of the loop variable. No matter how the loop variable changes later, the value that has been bound to the function parameter remains the same:


>>> def count():
...  def f(j):
...   def g():
...    return j * j
...   return g
...  fs = []
...  for i in range(1, 4):
...   fs.append(f(i))
...  return fs
... 
>>> f1, f2, f3 = count()
>>> f1()
1
>>> f2()
4
>>> f3()
9

conclusion


Related articles: