python之路6-迭代器、生成器、装饰器
1、迭代器&生成器
列表生成式
现在有个需求,列表[1,2,3,4,5,6,7,,8,9],要求把列表里的每个值加1,如何实现?
方法一:
list = [1,2,3,4,5,6,7,8,9] for index,i in enumerate(list):
list[index] = i + 1 print(list)
运行结果:
[2, 3, 4, 5, 6, 7, 8, 9, 10]
方法二:
list = [1,2,3,4,5,6,7,8,9]
#map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 列表list,并通过把函数 f 依次作用在 list 的每个元素上,
# 得到一个新的 list 并返回
a = map(lambda x:x+1,list)
for i in a:
print(i)
运行结果:
[2, 3, 4, 5, 6, 7, 8, 9, 10]
其实,还有一种写法
list = [1,2,3,4,5,6,7,8,9]
a = [x+1 for x in list]
print(a)
运行结果:
[2, 3, 4, 5, 6, 7, 8, 9, 10]
这就叫做列表生成式
生成器
通过列表生成式,我们可以创建一个列表,但是,受到内存限制,列表容量是有限的。而且,创建一个包含100百万元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间就白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可在循环过程中不断推算出后面的元素呢?这样就不需创建完整的列表,从而节省大量空间。在python中,这种一边循环一边计算的机制,称为生成器:generator。创建一个generator,有很多中方法,第一种方法很简单,只要把列表生成式中的[]改成(),就创建了一个generator。
a = [x+1 for x in range(10)]
print(a)
a = (x+1 for x in range(10))
print(a)
运行结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
<generator object <genexpr> at 0x0000017258EF2830>
generator要打印出来,需要通过next()函数获得generator的返回值
print(next(a))
1
print(next(a))
2
generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象:
for i in a:
print(i)
generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。
比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ..
斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:
def fib(max):
n,a,b=0,0,1
while n<max:
print(b)
a,b=b,a+b
n +=1
return 'done' fib(10)
仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。
也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:
def fib(max):
n,a,b=0,0,1
while n<max:
yield b
a,b=b,a+b
n +=1
return 'done'
这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。yield相当于一个断点
f = fib(10)
print(f.__next__())
print(f.__next__())
print("干点别的事")
print(f.__next__())
print(f.__next__())
运行结果:
1
1
干点别的事
2
3
同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代:
for i in fib(10):
print(i)
迭代器
我们已经知道,可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
可以使用isinstance()判断一个对象是否是Iterable对象:
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
个人理解:生成器就是迭代器
3、装饰器
软件开发原则:开放-封闭,不能改变原代码的调用方式。
- 封闭:已实现的功能代码块不应该被修改
- 开放:对现有功能的扩展开放
闭包函数:python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。
import time
def timer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)#执行index原始函数
stop_time = time.time()
print('run time is %s' %(stop_time-start_time))
return res
return wrapper @timer #index=timer(index)
def index(msg):
print('in the index: ',msg)
return 1
res=index('hello world') #wrapper('hello world')
print(res)
# 装饰器执行流程:
# 1、导入time模块
# 2、定义timer函数,函数名作为变量名赋值给timer函数
# 3、@timer index赋值给timer函数
# 4、定义闭包函数wrapper,直接返回wrapper
# 5、定义index函数
# 6、执行index函数,实际是执行timer函数的返回值wrapper函数
有参装饰器
python之路6-迭代器、生成器、装饰器的更多相关文章
- python学习笔记(5)--迭代器,生成器,装饰器,常用模块,序列化
生成器 在Python中,一边循环一边计算的机制,称为生成器:generator. 如: >>> g = (x * x for xin range(10)) >>> ...
- Python基础-迭代器&生成器&装饰器
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...
- Python 迭代器&生成器,装饰器,递归,算法基础:二分查找、二维数组转换,正则表达式,作业:计算器开发
本节大纲 迭代器&生成器 装饰器 基本装饰器 多参数装饰器 递归 算法基础:二分查找.二维数组转换 正则表达式 常用模块学习 作业:计算器开发 实现加减乘除及拓号优先级解析 用户输入 1 - ...
- 迭代器/生成器/装饰器 /Json & pickle 数据序列化
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需 ...
- 4.python迭代器生成器装饰器
容器(container) 容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中.通常这类数据结构把所有的元素存储在内存中 ...
- python中的迭代器&&生成器&&装饰器
迭代器iterator 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束. 迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外, ...
- Python学习——迭代器&生成器&装饰器
一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...
- Python 全栈开发五 迭代器 生成器 装饰器
一.迭代器 迭代协议:对象必须提供一个next方法,执行该方法后会返回迭代的下一项或者抛出Stopiteration异常,终止迭代.切只能往前,不能倒退. 可迭代对象:遵循迭代写一点对象就是可迭代对象 ...
- python中的迭代器 生成器 装饰器
什么迭代器呢?它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()(python2中实现next())方法的对象都是迭代器,_ ...
- Python迭代器&生成器&装饰器
1. 迭代器 1.1 可迭代对象(Iterator) 迭代器协议:某对象必须提供一个__next__()方法,执行方法要么返回迭代中的下一项,要么引起一个Stopiteration异常,以终止迭代(只 ...
随机推荐
- licecap软件——简单做出app的效果gif图
最近想在博客或者是git上放gif效果图,找了许久,终于是找到了这款软件,不到500Kb大小,使用简单 软件名为licecap,直接百度上搜索即可 使用的话,打开软件,就会出现一个窗口 之后,可以改变 ...
- 树上倍增求LCA及例题
先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...
- ionic3 Toast组件
html页面 <button ion-button color="dark" class="button-block" (click)="sho ...
- <4>Python切片功能剖析
引用文章:https://mp.weixin.qq.com/s/NZ371nKs_WXdYPCPiryocw 切片基础法则: (1)公式,禁止0. (2)i, n同号:从序列的第i位索引起,向右取n- ...
- redis 慢日志查询
Intro 可能有一些命令需要很长时间才能在redis服务器上处理,导致请求超时. 长时间运行的命令的很少例子有 mget有大量的键,键*或写得不好的lua脚本. 可以运行通过 SlowLog 命令查 ...
- Django2.0 正则表示匹配的简单例子
在Django中,使用正则表达式,匹配Url 默认情况下,url固定格式如下: urlpatterns = [ path('admin/', admin.site.urls), ] 如果需要使用正则表 ...
- 多维数据库 Oracle Essbase 和 IBM Cogons 底层原理
多维数据库(Multi Dimensional Database,MDD)使用Dimension(维度)和Cube(数据立方体.数据集市)模型描述数据. 多维数据模型 关系型数据库(Relationa ...
- C#-事件event
目录 1. 简介 2.实际案例 2.1实际案例1 2.2实际案例2--带有参数的事件 3.标准事件的用法 3.1通过扩展EventArgs来传递数据 3.2代码实例 1. 简介 事件是一种类型安全的委 ...
- Windows系统资源监控
1.windows自带系统资源监控工具 2.Windows监控的数据来源:Performance Counters 2.1 Performance Counter架构 2.2 Performance ...
- kaptcha验证码的使用
使用kaptcha可以方便的配置: 验证码的字体 验证码字体的大小 验证码字体的字体颜色 验证码内容的范围(数字,字母,中文汉字!) 验证码图片的大小,边框,边框粗细,边框颜色 验证码的干扰线(可以自 ...