零基础入门Python3-函数式编程(3)

一、返回函数

函数作为 "返回值" 返回。特点是返回函数在调用的时候才运行计算。

# 实例1,求传入值的平方

def func(n):

    def func1():

        return n*n

    return func1

print(func(2))

>>>  <function func.<locals>.func1 at 0x00000000024CFA60>

在这个实例中,我们定义了两个函数,func1 返回的是一个平方值,而 func 返回的是 func1 这个函数本身。当我们调用 func 这个函数的时候,返回的是函数 func1,但是并没有计算出结果。

# 实例2,接上面的例子

#我们把func(2)赋值给变量 a,并且运行 a()

a=func(2)

print(a())

>>> 4

# 所以,只有运行 函数 a() 的时候,才会返回运算结果

我们来看一个返回函数的例子

# 实例3,返回1,2,3 的2倍的值

def func1():

    ls=[]

    for i in range(1,4):

        def func2():

            return i*2

        ls.append(func2)

    return ls

a1,a2,a3=func1()

print(a1())

print(a2())

print(a3())

>>> 6

       6

       6

# a1,a2,a3=func1(),这个是给这三个变量依次赋值,值为函数

# 按照我们的想法,这三个值应给为 2,4,6,为什么结果成了6,6,6 了?这里我们引入一个新的知识,这就是闭包。我们先不说解释什么是闭包,我们先来分析一下该函数的执行的顺序以及过程。

# 实例3分析

 

def func1():    

# 首先定义 func1 这个函数

    ls=[]    

# 接着定义 空的列表ls

    for i in range(1,4):

# for循环,并分次把 1,2,3 赋值给变量 i 

    for i in range(1,4):

        def func2():

            return i*2

        ls.append(func2)

    return ls

# 红色的部分为 for 循环的内部语句,for 循环的次数为3次。首先 for 每次循环都要创建新的函数 func2,函数的返回值为 变量 i * 2。函数创建完毕后,接着运行 ls.append(func2),添加的值为函数,并不是直接添加计算结果。for 循环完毕后,返回列表 ls。最后把函数 func1 的返回值分别赋值给 a1,a2,a3。

# 以上是程序的运行过程,我们接着来说内部的运行逻辑。当然,主要是红色部分的代码。

    for i in range(1,4):

        def func2():

            return i*2

        ls.append(func2)

# 首先,for 循环生成了 i=1 的变量,开始第一次循环,创建一个新的函数func2,接着运行ls.append(func2),向列表 ls 添加一个元素,这个元素是一个函数 fun2,但是函数并没有运行起来,而是相当于 "挂" 起来了,就此第一次循环完毕。

# 接着第二次循环,i=2,创建一个新的函数 func2,接着想 ls 添加函数 func2,和第一次一样,函数并没有运行,第二次循环完毕。

# 第三次循环 i =3,创建一个新的函数 func2,接着想 ls 添加函数 func2,和第一次一样,函数并没有运行,第三次循环完毕。

# 这时候,for 循环完,i 的值为3。接着返回列表 ls 。这时,函数 func1 也已经定义完。

# 运行 a1,a2,a3=func1(),把列表 ls 中的三个函数分别赋值给a1,a2,a3

# 接着运行 print(a1())  print(a2())  print(a3()),这时候的a1,a2,a3已经是代表的三个对应的函数。此时,函数 func2才真正的运行起来了,可 i 的值已经为3了。所以三个函数的输出值都为 6 。

# 函数的返回值为函数,且内部函数调用外部变量和参数的情况,称为闭包。(我是这么理解的==!见笑了),如果破解这种情况呢?我们看实例4

# 实例4,破解闭包

def func1():

    ls=[]

    for i in range(1,4):

        def func2(j):

            def func3():

                return j*2

            return func3

        ls.append(func2(i))

    return ls

a1,a2,a3=func1()

print(a1())

print(a2())

print(a3())

>>>  2

        4

        6

# 只需要再新建一个函数,把 for 循环的变量 i 的值,传入新函数的参数中,然后就可以放心的调用参数了。

 

二、匿名函数

使用 lambda 创建一个匿名函数。语法如下

lambda 参数1、参数2......:语句

- 匿名函数没有对应的函数变量,但可以自己指定变量

- 匿名函数只能有一个表达式

- 可以没有参数,参数也可以是可变参数、关键字参数和命名关键字

# 实例5

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

>>> [1, 4, 9, 16, 25, 36, 49, 64, 81]

# 可以利用 map 函数来构建list,方便快捷

# 实例6,两个参数,表达式为判断语句

a =lambda x,y:True if x>y else False

print(a(2,3))

>>> False

# 把匿名函数赋值给变量 a,在使用 a 往匿名函数带入参数

# 实例7,lambda 的可变参数

b=lambda *args:list(args)

print(b(1,2,3))

>>> [1, 2, 3]

# 事实证明,lambda 的参数也可以是可变参数

# 实例8,lambda 的关键字参数

c=lambda **kw:True if kw['name']=='zhangsan' else False

print(c(name='zhangsan',age=18))

>>> True

# 在一次证明,关键字参数也是可以的

# 实例9,lambda 的命名关键字参数

d=lambda name,age,*,job :'My name is '+name+', i am '+str(age)+", "+'job is '+job

print(d('zhangsan',18,job='Study'))

>>> My name is zhangsan, i am 18, job is Study

# 成功带入命名关键字参数

# 综上实例,我们可以看到,就参数而言,和正常函数是没有什么区别的。但是执行语句lambda只能有一个表达式,而正常函数是可以有很多的。

 

关注公众号,了解更多!

posted @ 2019-03-06 21:52  PyShadow  阅读(209)  评论(0编辑  收藏  举报