What is a closure? Two solutions to the python closure problem

Source: Internet
Author: User
Closure is to get different results based on different configuration information. Next, I will share with you two things to note about the Python closure. if you need a friend, refer to the closure to get different results based on different configuration information. The following are two things to note about the Python closure through this article. For more information, see

What is a closure?

To put it simply, closures get different results based on different configuration information.

Let's take a look at our professional explanation: Closure is short for Lexical Closure, a function that references free variables. This referenced free variable will exist with this function, even if it has left the environment where it was created. Therefore, there is another saying that a closure is an entity composed of a function and its reference environment.

Delayed binding

The external free variables referenced by the Python closure function are delayed.

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]

For example, the above code: I is a free variable in the external scope referenced by the closure function. the variable I value is searched only when the internal function is called. because the loop has ended, I points to the final value 3, so each function call gets the same result.

Solution:

1) bind the closure function immediately (use the default value of the function 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]

As shown in the above code: When a closure function is generated, we can see that each closure function has a parameter with the default value: I = I. at this time, the interpreter will look for the value of I, and assign it to the form parameter I. In this way, the variable I is found in the external scope of the generated closure function (that is, in the external loop), and the current value is assigned to the form 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]

For example, the code above: if there is a problem due to delayed binding, you can use functools. partial to construct partial functions so that free variables are preferentially bound to closure functions.

Do not rebind the referenced free variables in the closure function.

Python

Def foo (func): free_value = 8 def _ wrapper (* args, ** kwargs ): old_free_value = free_value # save the old free_value = old_free_value * 2 # simulate the generation of new free_value func (* args, ** kwargs) free_value = old_free_value return _ wrapperdef foo (func ): free_value = 8 def _ wrapper (* args, ** kwargs): old_free_value = free_value # save the old free_value = old_free_value * 2 # simulate and generate a new free_value func (* args, ** kwargs) free_value = old_free_value return _ wrapper

The above code will report an error, UnboundLocalError: local variable 'free _ value' referenced before assignment. the above code is intended to implement an initialization state (free_value) however, when executing the internal closure function, the new state (free_value = old_free_value * 2) can be changed as needed. However, due to the internal re-binding, the interpreter regards free_value as a local variable. if old_free_value = free_value, an error is returned because the interpreter assumes that free_value is referenced without a value assignment.

Solution:

When you want to modify the free variable referenced by the closure function, you can put it into a list. in this way, free_value = [8] and free_value cannot be modified, however, free_value [0] can be safely modified.

In addition, the nonlocal keyword is added to Python 3.x to solve this problem.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.