Python advanced: A closed packet carrying state

Source: Internet
Author: User
Closed Package

In Python, a function is also an object. Therefore, when defining a function, we can then nest the definition of a function and return the nested function, for example:

From math import Powdef make_pow (n):    def inner_func (x):     # nesting defines inner_func        return pow (x, n)   # Note that the N return inner_func # of the external function is referenced here to      return Inner_func

In the above code, the function Make_pow also defines an intrinsic function inner_func, and then returns the function. Therefore, we can use MAKE_POW to generate another function:

>> > Pow2 = Make_pow (2)  # Pow2 is a function, parameter 2 is a free variable >> > pow2<function inner_func at 0x10271faa0 ;>> > Pow2 (6) 36.0

We also note that the intrinsic function Inner_func refers to the free variable n of the external function make_pow, which means that when the function make_pow the end of the life cycle, n is still stored in the Inner_func, which is cited by Inner_func Use.

>> > del make_pow         # delete make_pow>> > pow3 = Make_pow (3) Traceback (most recent call last):    File "&L T;stdin> ", line 1, in < module >nameerror:    name ' Make_pow ' are not defined>> > pow2 (9)     # pow2 can still be Often called, the free variable 2 is still saved in Pow2 81.0

---|---

In this case, a function returns an intrinsic function that references the parameters and variables of the external function, which we call the inner function of the return closure (Closure).

In the example above, Inner_func is a closure, which refers to the free variable N.

The role of closures

    • The most important feature of closures is the use of free variables, even if the generated closure environment has been released, the closure still exists;

    • Closures can have multiple instances at run time, even if the parameters passed in are the same, such as:

>> > Pow_a = Make_pow (2) >> > Pow_b = Make_pow (2) >> > pow_a = Pow_bfalse
    • With closures, we can also emulate instances of classes.

This constructs a class that is used to find the distance from one point to another:

From math import Sqrtclass Point (object):    def __init__ (self, x, y):        self.x, self.y = x, y    def get_distance (sel F, U, v):        distance = sqrt ((self.x-u) * * 2 + (SELF.Y-V) * * 2)        return distance>> > pt = Point (7, 2) 
  
   # Create a point >> > pt.get_distance (6)  # Find the distance to another point 5.0
  

Use closures to achieve:

def point (x, y):    def get_distance (U, v):        return sqrt ((x-u) * * 2 + (Y-V) * * 2)    return get_distance>> > pt = Point (7, 2) >> > pt (10, 6) 5.0


As you can see, the result is the same, but using a closure implementation is more concise than using a class.

Common pitfalls

The concept of closures is simple, but the implementation is prone to some pitfalls, such as the following example:

def count ():    funcs = []    for I in [1, 2, 3]:        def f ():            return I        funcs.append (f)    return Funcs

In this example, we create a function in each for loop and save it to Funcs. Now, calling the above function, you might think that the return result is 1, 2, 3, which is actually not:

>> > F1, F2, F3 = count () >> > F1 () 3>> > F2 () 3>> > F3 (3)

Why is it? The reason is that the above function f refers to the variable i, but the function f is not immediately executed, when the For loop ends, at this time the value of the variable i is 3, the function inside the FUNCS reference variable is 3, the final result is all 3.

Therefore, we should try to avoid referencing the loop variable in the closure or the variable that will change later.

What should be done about this situation? We can then create a function and pass the value of the loop variable to the function, as follows:

def count ():    funcs = []    for I in [1, 2, 3]:        def g (param):            f = Lambda:param    # Here you create an anonymous function            return f        Funcs.append (g (i))        # Pass the value of the loop variable to G    return funcs>> > F1, F2, F3 = count () >> > F1 () 1>> &G T F2 () 2>> > F3 () 3

Summary

    • Closures are functions that carry free variables, even if the life cycle of the outer function that creates the closure ends, the free variables referenced by the closure will still exist.

    • Closures can have multiple instances running.

    • Try not to reference the loop variable in the closure, or the variable that will change later.

The above is the Python advanced: carrying status of the closure of the contents, more relevant content please pay attention to topic.alibabacloud.com (www.php.cn)!

  • Related Article

    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.