Python 闭包,生成式,推导式
闭包概念
闭包,又称闭包函数或者闭合函数,其实和前面讲的嵌套函数类似,
不同之处在于,闭包中外部函数返回的不是一个具体的值,而是一个函数。一般情况下,返回的函数会赋值给一个变量,这个变量可以在后面被继续执行调用。
内部函数使用了外部函数变量或参数,且外部函数返回了内部函数,则将这个使用了外部函数变量的内部函数称为闭包
闭包作用的特点如下
可以保存外部函数内的变量,不会随外部函数调用完而销毁
闭包可以提高代码的可重用性,无需再手动定义额外的功能函数
由于闭包引用了外部函数变量,外部函数变量没有及时释放,消耗内存
def test(x):
return x
def outter(func):
y = "你追我,"
def inner1():
nonlocal y
print(y, end="")
ret = func("如果你追到我,")
print(ret, end="")
return "我就让你嘿嘿嘿"
return inner1
ret = outter(test)()
print(ret)
------------------------
def outter():
name = "test"
def inner():
print("from inner,name is%s" % name)
return "inner函数"
return inner
a = outter()
print(a.__name__)
print(a())
----------------
运行结果如下
inner
from inner,name istest
inner函数
以上就是个闭包函数的典型示例,有如下特征:
- 一个外部函数outter内部会包裹多个inner子函数,因为函数的作用域关系,对inner函数而言,outer函数的name相对来说就是全局变量,
- inner 函数结束后 必须有个return inner 进行函数返回
outter的返回值指示inner函数的内存地址
闭包应用场景
闭包的实际应用场景更多在于异步调用(协程和多线程的异步).因为异步调用,函数每次执行完成需要的时间不同,有些变量无法从全局传入.最好的方式就是讲参数执行的时候就传入闭包中,因为作用域的关系.
局部变量彼此之间不会相互影响.

上面例子中 add_done_callback方法会再线程池调用完down函数以后,继续调用done函数,但是此时只能传入一个arg参数,里面的arg.result()就是前面down函数的返回值.
此时无法传入filename参数,也无法设置全局变量,因为我们要实现保存的文件名是不同的.
解决办法
办法1: 我们把filename这个参数也写入down的返回值中

办法2: 就是使用闭包函数,将filename参数传入闭包outter函数,在其outter内部作为全局变量,就可以将闭包体内将filename传入.
而且outter函数运行的时候会单独创建一个独立的内存栈.多线程并发运行的三个outter函数是作用与不同的内存地址的.所以他们内部的局部变量也是各自独立.

生成式和表达式的区别
明显的区别是生成式是(代码块),而表达式是[代码块]
用下面经典案例描述运作模式
def num():
return [lambda x: x * i for i in range(4)]
ret = [i(2) for i in num()]
print(ret)
输出结果是[6,6,6,6]
上面是表达式内用匿名函数生成的案例.
表达式的特点是遍历循环完毕后,再进行执行.
for i in num() 这句会先执行num函数,num执行结果返回的是一个列表,里面有4个匿名函数体,注意此时匿名函数体的x*i是不执行的,所以之前i再遍历循环传入的值是无效的.而for循环完毕后I就是为3.
因此num返回的列表可以理解为4个匿名函数被放入了一个列表.
接下来是[i(2) for i in num()]对4个匿名函数遍历循环 i就是匿名函数 i(2) = lammbda x:2*i,而匿名函数此时的i 就是上面循环完毕后的3.所以4个匿名函数都是计算结果都是2*3
-------------------------------
接下来是生成式,可以看到2个例子就是()和[]的区别,但是计算方式天差地别
def num():
return (lambda x: x * i for i in range(4))
ret = [i(2) for i in num()]
print(ret)
第一步一样,还是运行num函数,生成式的特点是生成一个,使用一个,前一个不使用,后面的就不生成.以此实现内存节约目的.
虽然都是运行num函数但是此时不会一次性生成4个,而是只生成一个匿名函数,
此时匿名函数的i=0 而x则会再i(2)执行的时候传入2,所以第一个返回值是0
第二个 匿名函数的i为1 而i(2)传入的x为2 返回值为2
第三个 匿名函数的i为2 而i(2)传入的x为2 返回值为4
第四个 匿名函数的i为3 而i(2)传入的x为2 返回值为6
生成式的斐波那契数列的示例
def fib(max_count):
first = 1
second = 0
count = 0
while count<max_count:
nex_val = second+first
first,second = second,second+first
yield nex_val
count+=1
for i in fib(5):
print(i)
迭代器 和生成器
理论知识
迭代器 内部有__iter__和__next__方法 前者返回自身,后者可以获取数据,当数据获取完毕后抛出Stopiterration的异常
生成器 函数中有yield就是生成器函数,执行函数返回的就是生成器对象(特殊的迭代器),可以通过next方法取值
可迭代对象 内部有__iter__方法且返回一个迭代器对象,可以被for循环遍历
Python 闭包,生成式,推导式的更多相关文章
- python基础——列表推导式
python基础--列表推导式 1 列表推导式定义 列表推导式能非常简洁的构造一个新列表:只用一条简洁的表达式即可对得到的元素进行转换变形 2 列表推导式语法 基本格式如下: [expr for va ...
- Python生成器、推导式之前襟后裾
生成器 函数体内有yield选项的就是生成器,生成器的本质是迭代器,由于函数结构和生成器结构类似,可以通过调用来判断是函数还是生成器,如下: def fun(): yield "我是生成器& ...
- python的各种推导式
python的各种推导式(列表推导式.字典推导式.集合推导式) 推导式comprehensions(又称解析式),是Python的一种独有特性.推导式是可以从一个数据序列构建另一个新的数据序列的结构体 ...
- Python基础-列表推导式
python中列表推导式有三种数据类型可用:列表,字典,集合 列表推导式书写形式: [表达式 for 变量 in 列表] 或者 [表达式 for 变量 in 列表 if 条件] 1,列表推导式 ...
- python 3列表推导式的的一点理解!
python 3列表推导式的的一点理解! Python的列表推导式对于新手来说一般都难以理解,简单看个例子: [x * x for x in range(1,100)] 上面是一个很简单的列表推导式, ...
- Python 入门之 推导式
Python 入门之 推导式 推导式就是构建比较有规律的列表,生成器,字典等一种简便的方式 1.推导式 (1)列表推导式 : <1> 普通循环: [变量 for循环] print([i f ...
- 12.Python略有小成(生成器,推导式,内置函数,闭包)
Python(生成器,推导式,内置函数,闭包) 一.生成器初始 生成器的本质就是迭代器,python社区中认为生成器与迭代器是一种 生成器与迭代器的唯一区别,生成器是我们自己用python代码构建成的 ...
- Python函数——列表推导式、生成器与迭代器
列表推导式 产生背景 现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求你把列表里的每个值加1,你怎么实现? 第一种方法: a = [1,3,4,6,7,7,8,9 ...
- 『无为则无心』Python序列 — 24、Python序列的推导式
目录 1.列表推导式 (1)快速体验 (2)带if的列表推导式 (3)多个for循环实现列表推导式 2.字典推导式 (1)创建一个字典 (2)将两个列表合并为一个字典 (3)提取字典中目标数据 3.集 ...
- Python的列表推导式
1.列表推导式书写形式: [表达式 for 变量 in 列表] 或者 [表达式 for 变量 in 列表 if 条件] 2.举例说明: #!/usr/bin/python # -*- codi ...
随机推荐
- [seaborn] seaborn学习笔记8-避免过度绘图Avoid Overplotting
8 避免过度绘图Avoid Overplotting(代码下载) 过度绘图是散点图及几天常见图表中最常见的问题之一.如下图所示当数据集很大时,散点图的点会重叠,使得图形变得不可读.在这篇文章中,提出了 ...
- 使用SQL4Automation让CodeSYS连接数据库
摘要:本文旨在说明面向CodeSYS的数据库连接方案SQL4Automation的使用方法. 1.SQL4Automation简介 1.1.什么是SQL4Automation SQL4Auto ...
- Spring 和 Spring MVC的区别
Spring 和 Spring MVC的区别 学习Spring MVC也有几天时间了,那么Spring和Spring MVC的区别到底在哪里,二者是什么关系呢?认为二者是一个东西那肯定是不对的,而 ...
- strapi系列-如何去除接口里的attributes以及 data key,配置关联数据等
我们先来创建一个接口,然后看一下正常接口返回的数据格式是什么样子 创建表以及字段 添加一条数据 配置接口权限 我暂时给了这个接口PUBLIC权限,用来测试 使用postman进行接口测试 我们可以看到 ...
- Java入门与进阶P-4.5+P-4.6
逻辑类型 关系运算的结果是要给逻辑值,true或false.这个值可以保存在一个对应的逻辑类型变量中,这样的变量类型是boolean 布尔是为了纪念George Boole对逻辑计算得到贡献 bool ...
- SkyWalking安装及SkyApm运行(.net和java)
一.部署SkyWalking 1.下载SkyWalking包(版本为6.6.0) 下载地址为:http://skywalking.apache.org/downloads/ 2.修改数据库配置 默认为 ...
- Timer的定时调度函数schedule的四种用法
schedule的四种用法 schedule(task,time) task-所安排的任务 time-执行任务的时间 作用:在时间等于或者超过time的时候执行且仅执行一次 import java. ...
- ASP.NET Core 系列总结
<ASP.NET Core> 系列文章基于 .NET 3.1 和 .NET 6,主要是系统总结自己日常工作和学习中的知识点,之前是自己在 OneNote 上自己写,作为学习.总结笔记,逐渐 ...
- Emacs单文件配置
编辑 ~/.emacs 输入以下内容 ;; 编码 (set-language-info "UTF-8" 'coding-priority '(utf-8 gb18030 gbk g ...
- 亚马孙机器可能出现权限问题导致ssh无法秘钥登录的情况
一般都是amazon会遇到,目前ali的机器没遇到过 情况是新机器,然后ssh脚本创建目录和用户和拷贝秘钥等等,后面用该新用户的秘钥登录发现一直无法登录. 把sshd的log改为debug,查看日志得 ...