Python3学习(15)--惰性函数

Python的函数太丰富了,讲起来稍微有点费劲,如果给你一个函数简单使用的话,你大可不必深入去了解这个函数,但是作为一个学习者来说尽管不知道以后这个函数我们还会不会遇到,会不会使用到,我们也要尝试去和它打交道,深入的打交道,尽自己所理解的,去阐述它;


上一篇我们简单的配置了wing开发IDE,这篇,我们就结合一下它,来讲一下我们今天的主角,惰性函数,又称返回函数;

函数,我们知道它可以出现在参数里,像我们的高阶函数那样,当然,我们也能猜出来,它也可以出现在函数的返回值位置上,但是,实际上我们没有这样做过,因为,我们写函数的目的就是为了实现自己的想要的功能,这种实现需要是实时的,需要我们调用这个函数结束后,就能切身的体会到函数带给我们的便利,然而我们今天要讲的这个惰性函数,却是滞后的,如果你想显得自己很高深,用了它,请一定要小心,否则,会有麻烦的。


看个例子,简单认识一下惰性函数:

我们定一个函数,函数的功能是播报一条新闻,我们取名叫cast_News,当然,大部分情况下,新闻都是提前写好,按点播出的,所以,我们让这个播报新闻的动作(函数)先返回出去,至于具体谁来操作这个函数,我们不知道,因此,最外层,还要定一个顶层函数,这个顶层函数有一个参数,播报者的姓名,并且,这个函数的返回值是这个cast_News:


我们看下demo:

#/usr/bin/env Python3
#-*- encoding:UTF-8 -*-
'''
  返回函数,顾名思义,就是一个函数的返回值是一个函数
  Java、C#中返回一个函数,是不是听起来怪怪的,好像也不能吧
  C/C++可以做到返回函数的指针
  但是,像Python这种直接返回函数名的,真是大胆创新啊
'''
def cast(Name):
    def cast_News():
        print(Name,'现在开始播报新闻:巴铁痛揍印度阿三,大块人心!')
    return cast_News

f1 = cast("appleyk") #cast 是一个懒惰函数,复杂点就是一个返回值是函数的函数,调用并不马上执行
f2 = cast('Bob')     #注意,返回的函数地址不是同一个
print(f1)
print(f2)
print(f1==f2)        #验证f1和f2是否指向的函数地址入口相等 
f1()
f2()   #这个时候,我们才真正的具体的将这个播报新闻这一行为给实施了

我们看下执行结果:


上面我们只是简单的定义了一个惰性函数,并知道,它在什么时候被真正调用,我们之前说过,如果你的项目中用了惰性函数,那么,你就要小心了,为什么呢,我们下面接着看一个例子:

我们这里只针对一个播报员,我们不再让他播报一条新闻,而是播报三条新闻,和上面的一样,我们不知道这三条新闻什么时候会播出,所以,我们仍然使用惰性函数来保留播报新闻这一行为(函数),demo设计如下:

#/usr/bin/env Python3
#-*- encoding:UTF-8 -*-
'''
  返回函数,顾名思义,就是一个函数的返回值是一个函数
  Java、C#中返回一个函数,是不是听起来怪怪的,好像也不能吧
  C/C++可以做到返回函数的指针
  但是,像Python这种直接返回函数名的,真是大胆创新啊
'''


def cast(Name):
    fL = [] #函数列表(数组)
    for s in ['新闻A','新闻B','新闻C']:
        def cast_News():
            return Name+',开始播报'+s
        fL.append(cast_News) #每循环一次,把播报新闻这一行为存到函数列表fL里,
        #根据cast_News函数的返回值,我们会以为,第一个播报新闻的行为肯定是针对新闻A的
        #-----------------------------------第二个播报新闻的行为肯定是针对新闻B的
        #-----------------------------------第三个播报新闻的行为肯定是针对新闻C的
    return fL #最后我们返回这个函数列表

#我们针对上面的猜想,我们来验证一下:
for f in cast("appleyk"): #注意,f取出的是一个函数入口地址,如使用,请写完整f()
    print(f())
我们看下,Debug结果,是不是我们猜想的:


为了跟踪一下函数的执行情况,我们利用鼠标左键轻轻的打个断点,然后F5开始调试,F7单步执行,当我们循环到第二层播报时,我们发现如下:


我们发现,s确实等于过 '新闻B',那为什么新闻B没有出现在播报里呢,我们继续F7单步执行下去,直到第三层循环(结束):


以上的这种在惰性函数里面声明一个局部变量,然后返回函数使用了这个局部变量,且这个局部变量可能会被多个新返回的函数共用,我们称这种行为叫闭包


官网说法这样说的:

在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
....

如何避开闭包,这就需要在局部变量上动手脚,我们可以这样做,每次循环的时候,我们不再定义一个播报新闻的函数让他每次都返回新闻内容,而是我们在循环的外面,再定一个惰性函数,而这个惰性函数里面放我们的播报新闻,这样的话,每次循环,我们添加这个播报行为到fL中,因为我们用了惰性函数的返回值绑定了我们的播报新闻内容,而这个返回值不可能共用一个地址,因此,我们这个时候,已经做到了,新闻A、B、C独立存储了,我们针对上面说的,改下demo:
#/usr/bin/env Python3
#-*- encoding:UTF-8 -*-
'''
  返回函数,顾名思义,就是一个函数的返回值是一个函数
  Java、C#中返回一个函数,是不是听起来怪怪的,好像也不能吧
  C/C++可以做到返回函数的指针
  但是,像Python这种直接返回函数名的,真是大胆创新啊
'''


def cast(Name):
    fL = [] #函数列表(数组)
    def news(s): #我们再定义一个惰性函数,返回我们的播报新闻函数,这个函数有个新闻内容参数
        def new():
            return Name+',开始播报'+s
        return new #这里,我们就可以将不同的新闻加进不同的播报行为里,而不会发生同一个新闻被播报N次
    for s in ['新闻A','新闻B','新闻C']:
        fL.append(news(s)) #这里,我们循环加入播放行为,局部变量s已经作为参数传递出去了
    return fL #最后我们返回这个函数列表

#我们看下,这个时候,我们输出的会是什么结果呢?
for f in cast("appleyk"):
    print(f())

来吧,我们看下执行结果:

这个惰性函数,讲起来特别绕,好在,我们有IDE,可以去单步跟踪函数的执行顺序和监控变量值的变化,从而发现端倪,实际上,我们会这样写函数吗?大多数情况下我们不会,但是,既然Python支持这种函数,我们就要去了解一下它,不然,真等我们工作或是学习中遇到了,我们肯定傻眼了。



结束语:

惰性函数告诉我们,它不是真的懒,而是它在等待时机,等一个可以让自己发挥奇效的人出现,也许能等到,也许等不到,总之,它很被动;

我们不要像惰性函数那样,生来就是等待机会的,我们要向高阶函数那样,寻找目标,主动出击,生活才能如沐春风,如鱼得水。


  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
函数式编程是一种编程范式,它将计算视为数学函数的求值过程。Python作为一门多范式的编程语言,也支持函数式编程。在函数式编程中,函数被视为一等公民,可以作为参数传递给其他函数,也可以作为返回值返回。函数式编程强调不可变性和无副作用,通过使用纯函数来实现。 在Python中,函数式编程可以通过以下几个特性来实现: 1. 高阶函数Python中的函数可以作为参数传递给其他函数,也可以作为返回值返回。这使得我们可以使用高阶函数来实现函数的组合、柯里化等功能。 2. 匿名函数Python中的lambda表达式允许我们创建匿名函数,这些函数可以在需要时直接定义,而不需要使用def关键字进行命名。 3. map、filter和reduce函数:这些内置函数函数式编程的重要工具。map函数可以将一个函数应用于一个可迭代对象的每个元素,并返回一个新的可迭代对象;filter函数根据指定的条件过滤可迭代对象中的元素,并返回一个新的可迭代对象;reduce函数对可迭代对象中的元素进行累积操作,返回一个单一的结果。 4. 列表推导式和生成器表达式:这些语法结构允许我们使用简洁的方式创建新的列表或生成器,从而实现对可迭代对象的转换或筛选。 5. 不可变性:函数式编程强调不可变性,即函数的参数和局部变量在函数执行期间不可修改。Python中的元组和frozenset等不可变对象可以用来实现这一特性。 6. 递归:函数式编程常常使用递归来解决问题,通过函数自身调用来实现循环和迭代的效果。 总结起来,Python函数式编程提供了一系列工具和语法结构,使得我们可以更加方便地使用函数作为一等公民,并且实现函数的组合、柯里化、惰性求值等特性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值