Python3 学习笔记22_函数式编程-返回函数_20180313

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 学习网站:www.liaoxuefeng.com

#****************************************************
#       Python3 函数式编程-返回函数                  *
#****************************************************
print ("--------------------分割线------------------")

#============
# 函数作为返回值
#============

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

# 普通的可变参数求和
def calc_sum(*args):
    ax = 0
    for n in args:
        ax = ax + n 
    return ax

# 不需要立即求和,可以不返回求和的结果,而是返回求和的函数
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

func = lazy_sum(1, 3, 5, 6)
print( func )   # <function lazy_sum.<locals>.sum at 0x0000021EDF06E7B8>
print( func() )                         # 15

# 调用lazy_sum函数时,每次调用都会返回一个新的函数,即使传入相同的参数
# func1() 和 func2()的调用结果互不影响。
func1 = lazy_sum(2, 3, 4, 5)
func2 = lazy_sum(2, 3, 4, 5)
print( func1==func2 )                   # False
print ("--------------------分割线------------------")

#============
# 闭包
#============
'''
在上面lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数
lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都
保存在返回的函数中,这种称为“闭包(Closure)”

注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回
了一个函数后,其内部的局部变量还被新函数所引用
'''
### 一定要注意:返回的函数并没有立刻执行,而是知道调用了fun()才执行
def count():
    list_a = []
    for i in range(1, 4):
        def fun():
            return i*i
        list_a.append(fun)
    return list_a

list_b = list( count() )

for func in list_b:
    print( func(),end = ' ' )               # 9 9 9 
print()

'''
在上面例子中,每次循环,都创建了一个新的函数,然后,把创建的3个函数都
返回了, 调用func()的结果不是1,4,9。正确结果全部都是9!,原因是返回
的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的
变量i已经变成了3,因此最终的结果是9.

!!!返回闭包时牢记一点:返回函数尽量不要引用任何循环变量,或者后续会发生
!!!变化的变量
'''

# 如果一定要引用循环变量:再创建一个函数,用该函数的参数绑定循环变量
# 当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变
def count1():
    def fun(j):
        def g():
            return j*j
        return g
    list_a = []
    for i in range(1, 4):
        list_a.append( fun(i) ) #fun(i)立刻被执行,i的当前值被传入fun() 
    return list_a

fun1,fun2,fun3 = count1()
print( fun1(), fun2(), fun3() )         # 1 4 9
print ("--------------------分割线------------------")

# 利用闭包返回一个计数器函数,每次调用它返回递增整数
def createCounter():
    i = [0]
    def counter():
        i[0] = i[0] + 1
        return i[0]
    return counter

aaa = createCounter()
print( aaa(), aaa(), aaa() )            # 1 2 3
'''
解析:
外部变量i=[0],每次调用内部函数,i都指向这个只有一个元素的list
牢记list是可变对象,i指向list这个关系在每次调用中是没有发生改变的
但是list内部第一个元素i[0]指向的数字在每次调用后已经加1了
第一次调用,(内部函数,i=[0]),i[0]+1,i[0]=1,返回1
下一次调用,(内部函数,i=[1]),i[0]+1,i[0]=2,返回2
(注意这里i还是指向原来的那个list,内部函数并没有改变外部变量i的指向)
'''

def createCounter1():
    i = 0
    def counter():
        nonlocal i
        i = i + 1
        return i
    return counter

bbb = createCounter1()
print( bbb(), bbb(), bbb() )            # 1 2 3
'''
解析:nonlocal适用于嵌套函数中内部函数修改外部变量的值,表示这个变量
不是局部变量空间的变量,需要向上一层变量空间找这个变量。
'''
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值