热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

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支持这种函数,我们就要去了解一下它,不然,真等我们工作或是学习中遇到了,我们肯定傻眼了。



结束语:

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

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



推荐阅读
  • Python3怎么获取文件属性
    这篇文章给大家分享的是有关Python3怎么获取文件属性的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。os.stat(path ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • Python爬虫中使用正则表达式的方法和注意事项
    本文介绍了在Python爬虫中使用正则表达式的方法和注意事项。首先解释了爬虫的四个主要步骤,并强调了正则表达式在数据处理中的重要性。然后详细介绍了正则表达式的概念和用法,包括检索、替换和过滤文本的功能。同时提到了re模块是Python内置的用于处理正则表达式的模块,并给出了使用正则表达式时需要注意的特殊字符转义和原始字符串的用法。通过本文的学习,读者可以掌握在Python爬虫中使用正则表达式的技巧和方法。 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
  • python教程分享Python获取时光网电影数据的实例代码
    一、前言有时候觉得电影真是人类有史以来最伟大的发明,我喜欢看电影,看电影可以让我们增长见闻,学习知识。从某种角度上而言,电影凭借自身独有的魅力大大延长了人类的”寿命&r ... [详细]
  • 浅谈Python3中打开文件的方式(With open)
    浅谈Python3中打开文件的方式(With open)-目录0.背景知识1.常规方式:读取文件-----open()2.推荐方式:读取文件-----WithOpen1).读取方式 ... [详细]
  • python教程分享python人物视频背景替换实现虚拟空间穿梭
    引言近期网上这位卖蜂蜜的小伙鬼畜挺火的,大家质疑背景造假,这里我就带着大家实现“背景造假”(ps:原视频小伙是在真实场景拍摄的)准备工作在实现该功能之前,我 ... [详细]
  • importurllib.requestimportos#用于获取煎蛋网页面的函数defurl_open(url):requrllib.request.Request(url) ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 本文由编程笔记#小编为大家整理,主要介绍了源码分析--ConcurrentHashMap与HashTable(JDK1.8)相关的知识,希望对你有一定的参考价值。  Concu ... [详细]
  • Python3从入门到放弃最后更新时间:2017-09-2503:05目录:第一章:HelloWorld第二章:输入和输出附录:常用的Python内置函数第一章:Hell ... [详细]
author-avatar
qyuyo0606
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有