Python10000小时计划——返回函数、匿名函数

匿名函数

 lambda表示匿名函数

“lambda 表达式1:表达式2”其实就是定义了一个函数,传入表达式1的参数,按表达式2的形式返回

list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))

 

匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

好处:不必担心函数名冲突

练习题 :用匿名函数改造下面代码

# -*- coding: utf-8 -*-
def is_odd(n):
return n % 2 == 1

L = list(filter(is_odd, range(1, 20))) #原语句
L = list(filter(lambda x: is_odd(x), range(1,20)))   #改造后
L1=list(filter(lambda x:x%2==1,range(1,20)))  #改造后2.0
print(L)
print(L1)

 

 

 

返回函数

高阶函数除了可以接受函数作为参数之外,还可以把函数作为返回值。

通常我们也可以通过以下方式求和:

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

 

但如果有一种情况 ,不需要立刻得出求和结果,而是在后续的代码中根据需要再计算,这种情况不返回求和的结果,而是返回求和的函数:

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

x=lazy_sum(1,3,5)
#返回值赋给x,x是一个代入(2,3,5)元组局部变量的函数funcsum()
#通过输出可以看出x是一个函数
print(x)
#需要调用x()时候才输出求和结果
print(x())

 

对于上例,调用lazy_sum()时候传入的参数(1,3,5)成为了新创建的funcsum()函数的内部变量,这样的程序结构也称为“闭包(Closure)”。

需要注意,即便传入同样的参数,返回的函数也是不同的:

x1=lazy_sum(1,3,5)
x2=lazy_sum(1,3,5)
print(x1==x2)  #False

 

需要注意的是,返回函数并不立即执行,直到需要调用它的时候才执行,根据执行的时候各个参数和变量的值输出结果,看下面的例子: !难点

def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs   #返回一个函数列表

f1, f2, f3 = count()
fx=count()
print(f1())
print(f2())
print(f3())
print(fx[0]())
print(fx[1]())
print(fx[2]())

 

以上输出全为9,是因为在生成(返回)f1,f2,f3和函数列表fx的时候,它们内部的变量是i,而在执行的时候i已经变成了3。所以在

使用闭包时需要牢记:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

如果一定要使用循环,那只有再创建一个函数,把循环变量绑定到其参数上,这样的绑定在循环过程中就实现了,可以保证循环后也不变:

def mycount():
    def f(j):
        def g():
            return j*j
        return g
    fs=[]
    for i in range(1,4):
        #此时i在循环中已经把值传递给g函数的参数j了
        fs.append(f(i))
    return fs

myf=mycount()
print(myf[0]())
print(myf[1]())
print(myf[2]())

 

 

 

练习:利用闭包返回一个计数器函数,每次调用它返回递增整数

#方法一:创建生成器:
[python] view plain copy
def createCounter():  
    def f():  
        x = 0  
        while True:  
            x += 1  
            yield x  
    it = f()  
  
    def number():  
        return next(it)  
    return number  
  
#createA = createCounter()  
#print(createA())  


#方法二:列表
[python] view plain copy
def createCounter():  
    f = [0]  
    def increase():  
        f[0] = f[0] + 1  
        return f[0]  
    return increase  
  
#createA = createCounter()  
#print(createA())  
#print(createA())  
#print(createA())  



# 测试:
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
counterB = createCounter()
if [counterB(), counterB(), counterB(), counterB()] == [1, 2, 3, 4]:
    print('测试通过!')
else:
    print('测试失败!')

 

 

 









posted @ 2018-06-04 18:19  33-林俊凯  阅读(77)  评论(0)    收藏  举报