[1-2] Back Advanced Python function | function as a return value, closure




1, as a function of return value

Python function can only return int, str, list, dict data types, functions can also return!

For example, the definition of a function f (), we return it to a function g, can be written like this:

def f():
    print 'call f()...'
    # 定义函数g:
    def g():
        print 'call g()...'
    # 返回函数g:
    return g

Carefully observe the function definition above, we are inside the function f and defines a function g.
Since g is an object, the function name is a pointer variable function g g, therefore, the outermost layer of the function f can return variable g, which is itself a function g.

Call the function f, we will get a return of the function f:

>>> x = f()   # 调用f()
call f()...
>>> x   # 变量x是f()返回的函数:
<function g at 0x1037bf320>
>>> x()   # x指向函数,因此可以调用
call g()...   # 调用x()就是执行g()函数定义的代码

Please note the distinction between the function return value and return:

def myabs():
    return abs   # 返回函数
def myabs2(x):
    return abs(x)   # 返回函数调用的结果,返回值是一个数值

Example 2.
We variable parameters to achieve a summation. Typically, the summation function is defined as:

def calc_sum(*args):
    ax = 0
    for n in args:
        ax = ax + n
    return ax

However, if the sum is not required immediately, but later in your code, as required, to calculate how to do again? The sum may not return results, but return function summation:

def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

When we call lazy_sum (), returns the sum is not the result, but the summation function:

>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
<function lazy_sum.<locals>.sum at 0x101c6ed90>

When you call the function f, really summation of the results:

>>> f()
25

In this example, we function lazy_sum he also defines a function sum, and internal function sum can reference external function lazy_sum arguments and local variables, when lazy_sum return function sum, the relevant parameters and variables are stored in the function returned , this is called "closure (closure)" program structure has great power.

Please note that when we call lazy_sum (), each call will return a new function, even if passed the same parameters:

>>> f1 = lazy_sum(1, 3, 5, 7, 9)
>>> f2 = lazy_sum(1, 3, 5, 7, 9)
>>> f1==f2
False
f1()和f2()的调用结果互不影响。

task:

Please write a function calc_prod (lst), which receives a list, returns a function, the function may return the product of calculated parameters.

CODE:

Can be calculated by defining the function of the product, this function then returns.

def calc_prod(lst):
    def lazy_prod():
        def f(x, y):
            return x * y
        return reduce(f, lst, 1)
    return lazy_prod
f = calc_prod([1, 2, 3, 4])
print f()


2, closure

  • Property within the function, all have a life cycle, it is present during the execution of the function;
  • Definition: the closure is a reference to an internal function of the external function in scope variables.
  • Closure function in the variable closure privatized, in fact, the encapsulated data is completed, similar to object-oriented.

Functions and external functions defined inside the function definition is the same, but they can not be accessed outside:

def g():
    print 'g()...'

def f():
    print 'f()...'
    return g

The function g is defined into the internal f, to prevent other code calls g:

def f():
    print 'f()...'
    def g():
        print 'g()...'
    return g

However, study on a section defined calc_sum functions:

def calc_sum(lst):
    def lazy_sum():
        return sum(lst)
    return lazy_sum

Note: lazy_sum found not to move outside calc_sum because it refers to calc_sum parameters lst.

This inner layer functions as a variable reference function layer (also considered a variable parameter), and then return to the situation of the inner function, called closure (Closure).

Characteristics of closure is also a reference function returns a function of the local variable layer, therefore, proper to use a closure, it is necessary to ensure that references to local variables can not be changed after the function returns.

For example as follows:

# 希望一次返回3个函数,分别计算1x1,2x2,3x3:
def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()

You might think to call f1 (), f2 () and f3 () result should be 1,4,9, but the actual results are all 9 (please verify yourself).

The reason is that when the count () function returns the three functions, three values ​​of the variable i in a reference function has become 3. Since f1, f2, f3 is not called, so this time they did not calculate i * i, when f1 is called:

>>> f1()
9     # 因为f1现在才计算i*i,但现在i的值已经变为3

Therefore, the function returns do not refer to any loop variables or variable subsequent changes occur.

task:

Return loop closure can not reference variables, please rewrite count () function, it returns the correct function can be calculated 1x1,2x2,3x3 of.

CODE:

def f(j):
    def g():
        return j*j
    return g

It can return a correct closure g, the variable g is not referenced by the loop variable j, thus normally performed.

Inside the loop count function, if the use of the function f, avoids references to the loop variable i.

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

Here Insert Picture Description

Published 20 original articles · won praise 0 · Views 401

Guess you like

Origin blog.csdn.net/yipyuenkay/article/details/104225594