Home  >  Article  >  Backend Development  >  What is a closure? Two solutions to problems about python closures

What is a closure? Two solutions to problems about python closures

Y2J
Y2JOriginal
2017-05-04 14:54:331486browse

Closure is to obtain different results based on different configuration information. Here are two things to note about Python closures through this article. Friends in need can refer to it

What is a closure?

Simple Said, closure is to obtain different results based on different configuration information.

Let’s take a look at the professional explanation: Closure is the abbreviation of Lexical Closure, which is quote of a free variable function. The referenced free variable will remain with the function even after it has left the environment in which it was created. Therefore, there is another way of saying that a closure is an entity composed of a function and its associated reference environment.

Lazy binding

External free variables referenced by Python closure functions are delayed bound.

Python

In [2]: def multipliers():
  ...:   return [lambda x: i * x for i in range(4)] 
In [3]: print [m(2) for m in multipliers()]
[6, 6, 6, 6]
In [2]: def multipliers():
  ...:   return [lambda x: i * x for i in range(4)] 
In [3]: print [m(2) for m in multipliers()]
[6, 6, 6, 6]

Such as the above code: i is a free variable in the external scope referenced by the closure function, which will only be ## when the internal function

is called #Search for the value of variable i. Since the loop has ended and i points to the final value 3, each function call gets the same result. Solution:

1) Bind immediately when generating the closure function (Use the default value of the function

formal parameter):

Python

In [5]: def multipliers():
  return [lambda x, i=i: i* x for i in range(4)]
    ...: 
In [6]: print [m(2) for m in multipliers()]
[0, 2, 4, 6]
In [5]: def multipliers():
  return [lambda x, i=i: i* x for i in range(4)]
    ...: 
In [6]: print [m(2) for m in multipliers()]
[0, 2, 4, 6]

Such as the above code: When generating a closure function, you can see that each closure function has a parameter with a default value: i=i, at this time, the interpreter will Find the value of i and assign it to the formal parameter i. In this way, in the outer scope of the generated closure function (that is, in the outer loop), the variable i is found, and its current value is assigned to the formal parameter i.

2) Use functools.partial:

Python

In [26]: def multipliers():
  return [functools.partial(lambda i, x: x * i, i) for i in range(4)]
  ....: 
In [27]: print [m(2) for m in multipliers()]
  [0, 2, 4, 6]
In [26]: def multipliers():
  return [functools.partial(lambda i, x: x * i, i) for i in range(4)]
  ....: 
In [27]: print [m(2) for m in multipliers()]
  [0, 2, 4, 6]

Such as the above code: When there may be problems due to delayed binding, you can construct it through functools.partial Partial functions allow free variables to be bound to closure functions first.

Prohibit rebinding of referenced free variables within the closure function

Python

def foo(func):
  free_value = 8
  def _wrapper(*args, **kwargs):
    old_free_value = free_value #保存旧的free_value
    free_value = old_free_value * 2 #模拟产生新的free_value
    func(*args, **kwargs)
    free_value = old_free_value
  return _wrapper
def foo(func):
  free_value = 8
  def _wrapper(*args, **kwargs):
    old_free_value = free_value #保存旧的free_value
    free_value = old_free_value * 2 #模拟产生新的free_value
    func(*args, **kwargs)
    free_value = old_free_value
  return _wrapper

The above code will Error reported, UnboundLocalError: local variable 'free_value' referenced before assignment, the above code is intended to implement an initialization

state

(free_value) but can be changed as needed when executing the internal closure function The decorator of the new state (free_value = old_free_value * 2), but due to internal rebinding, the interpreter will treat free_value as a local variable. If old_free_value = free_value, an error will be reported, because the interpreter thinks that free_value is assigned without a value. Cited.

Solution:

When you plan to modify the free variable referenced by the closure function, you can put it into a list, so that free_value = [8], free_value cannot be modified , but free_value[0] can be modified safely

.

In addition, Python 3.x added the nonlocal keyword, which can also solve this problem.

【Related recommendations】

1.

Python Free Video Tutorial

2. Python Learning Manual

3. python object-oriented video tutorial

The above is the detailed content of What is a closure? Two solutions to problems about python closures. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn