Pytho closures and decorators in detail

Source: Internet
Author: User
Tags mul
Closure (closure) is an important grammatical structure of functional programming. Closures are also a structure for organizing code, which also improves the reusable nature of code.

In an inline function, a reference to a variable within an external function (but not at the global scope) is considered a closure (closure).

variables defined within external functions but referenced or used by intrinsic functions are called free variables.

To summarize, creating a closure must meet the following points:

    • 1. Must have an inline function

    • 2. Inline functions must refer to variables in external functions

    • 3. The return value of the external function must be an inline function

1. Closure Use example

Let's look at a closure example:

In [ten]: def func (name):    ...:     def in_func (age):    ...:         print ' name: ', Name, ' Age: ', age    ...:     Return In_func ...    : in [all]: Demo = func (' Feiyu ') in []: Demo (Name:feiyu) age:19

Here a closure is generated when the call is made-and func in_func The closure holds the free variable- name so it also means that when the function func 's life cycle is over, name the variable still exists because it is referenced by the closure and is not recycled.

pythonwithin a function, an external variable can be referenced directly, but an external variable cannot be overridden, so an error occurs if the variable of the parent function is overwritten directly in the closure. Look at the following example:

To implement a count closure example:

def counter (start=0): Count = [start] def incr (): count[0] + = 1return Countreturn Incra = counter () print ' A: ', aIn [+]: def Counter (start=0):    ...:     count = Start    ...:     def incr ():    ...:         count + = 1    ...:         return Count    ...:     return incr ...    : in [+]: A = counter () in [+]: A ()  #此处会报错UnboundLocalError: Local Variable ' count ' referenced before assignment

It should be used as follows:

In [approx]: def counter (start=0):    ...:     count = [start]    ...:     def incr ():    ...:         count[0] + = 1< c19/> ...:         return count ...:     return incr ...    : in [PNS]: Count = Counter (5) in [Max]: For I in range: 
   ...:     print count (),    ...:     [6] [7] [8] [9] [10] [11] [12] [13] [14] [15]

2. Using closures for traps

In [1]: def create ():   ...:     return [Lambda x:i*x for I in range (5)]  #推导式生成一个匿名函数的列表   ...: in [2]: Create () Ou T[2]: [<function __main__.<lambda>>, <function __main__.<lambda>>, <function __main__. <lambda>>, <function __main__.<lambda>>, <function __main__.<lambda>>]in [4]: for Mul in Create ():   ...:     print mul (2) ...   :     88888

The result is not very strange, this is a closure of the use of a trap it! To see why?

In the above code, the function create returns a list stored 4 function variables, these 4 functions all reference the loop variable together, that i is, they share the same variable i , it i will change, when the function is called, the loop variable i is already equal to 4, so 4 functions return 8. If you need to use the value of the loop variable in the closure, the loop variable is used as the default parameter of the closure or is implemented by a partial function. The principle of implementation is also very simple, that is, when the loop variable is passed into the function, the new memory will be applied. The sample code is as follows:

In [5]: def create ():   ...:         return [Lambda x,i=i:i*x for I in range (5)]    ...: in [7]: For Mul in Create (): 
   ...:     print mul (2) ...   :     02468

3, Closures and decorators

An adorner is an application of a closure, except that it passes a function:

def addb (func):d EF Wrapper (): Return ' <b> ' + func () + ' </b> ' return wrapperdef Addli (func):d EF Wrapper (): Return ' <li> ' + func () + ' </li> ' return wrapper @addb         # equivalent to Demo = ADDB (Addli (demo)) @addli        # equivalent to Demo = Addli (Demo) def demo (): Return ' Hello World ' Print demo ()    # performed by Addb (Addku (demo))

At execution time, the function is passed to the demo addli adornment, and then the decorated function is passed to the decoration addb . So the result of the final return is:

<b><li>hello world</li></b>

4. Traps in the adorner

When you write an adorner acting on a function, the important meta-information of the function such as the name, document string, annotations, and parameter signatures are lost.

def out_func (func):d EF Wrapper ():        func () return Wrapper@out_funcdef demo (): "" "This is  a demo.    " " print ' Hello world ' if __name__ = = ' __main__ ':    demo () print "__name__:", Demo.__name__print "__doc__:", demo.__doc__

Look at the results:

Hello world.__name__: wrapper__doc__: None

Both the function name and the document string become closure information. Fortunately, you can use functools the adorner in the library @wraps to annotate the underlying wrapper function.

From Functools import wrapsdef Out_func (func):    @wraps (func) def wrapper ():        func () return wrapper

Try your own results!

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.