python 第三天(生成器 迭代器 装饰器 序列化)
来源:互联网 发布:wifi通话软件 编辑:程序博客网 时间:2024/06/04 19:35
一 生成器
生成器
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]
改成()
,就创建了一个generator:
>>> L
=
[x
*
x
for
x
in
range
(
10
)]
>>> L
这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return
语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()
的时候执行,遇到yield
语句返回,再次执行时从上次返回的yield
语句处继续执行。
二、迭代器
我们已经知道,可以直接作用于for
循环的数据类型有以下几种:
一类是集合数据类型,如list
、tuple
、dict
、set
、str
等;
一类是generator
,包括生成器和带yield
的generator function。
这些可以直接作用于for
循环的对象统称为可迭代对象:Iterable
。
可以使用isinstance()
判断一个对象是否是Iterable
对象:
而生成器不但可以作用于for
循环,还可以被next()
函数不断调用并返回下一个值,直到最后抛出StopIteration
错误表示无法继续返回下一个值了。
*可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
。
小结
凡是可作用于for
循环的对象都是Iterable
类型;
凡是可作用于next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列;
集合数据类型如list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象。
装饰模式有很多经典的使用场景,例如插入日志、性能测试、事务处理等等,有了装饰器,就可以提取大量函数中与本身功能无关的类似代码,从而达到代码重用的目的。下面就一步步看看Python中的装饰器。
一个简单的需求
现在有一个简单的函数”myfunc”,想通过代码得到这个函数的大概执行时间。
我们可以直接把计时逻辑方法”myfunc”内部,但是这样的话,如果要给另一个函数计时,就需要重复计时的逻辑。所以比较好的做法是把计时逻辑放到另一个函数中(”deco”),如下:
但是,上面的做法也有一个问题,就是所有的”myfunc”调用处都要改为”deco(myfunc)”。
下面,做一些改动,来避免计时功能对”myfunc”函数调用代码的影响:
经过了上面的改动后,一个比较完整的装饰器(deco)就实现了,装饰器没有影响原来的函数,以及函数调用的代码。例子中值得注意的地方是,Python中一切都是对象,函数也是,所以代码中改变了”myfunc”对应的函数对象。
装饰器语法糖
在Python中,可以使用”@”语法糖来精简装饰器的代码:
使用了”@”语法糖后,我们就不需要额外代码来给”myfunc”重新赋值了,其实”@deco”的本质就是”myfunc = deco(myfunc)”,当认清了这一点后,后面看带参数的装饰器就简单了。
被装饰的函数带参数
前面的例子中,被装饰函数的本身是没有参数的,下面看一个被装饰函数有参数的例子:
从例子中可以看到,对于被装饰函数需要支持参数的情况,我们只要使装饰器的内嵌函数支持同样的签名即可。
也就是说这时,”addFunc(3, 8) = deco(addFunc(3, 8))”。
这里还有一个问题,如果多个函数拥有不同的参数形式,怎么共用同样的装饰器?在Python中,函数可以支持(*args, **kwargs)可变参数,所以装饰器可以通过可变参数形式来实现内嵌函数的签名。
带参数的装饰器
装饰器本身也可以支持参数,例如说可以通过装饰器的参数来禁止计时功能:
通过例子可以看到,如果装饰器本身需要支持参数,那么装饰器就需要多一层的内嵌函数。
这时候,”addFunc(3, 8) = deco(True)( addFunc(3, 8))”,”myFunc() = deco(False)( myFunc ())”。
装饰器调用顺序
装饰器是可以叠加使用的,那么这是就涉及到装饰器调用顺序了。对于Python中的”@”语法糖,装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。
在这个例子中,”addFunc(3, 8) = deco_1(deco_2(addFunc(3, 8)))”。
Python内置装饰器
在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。
- staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,并且可以在类不进行实例化的情况下调用
- classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)
- property 是属性的意思,表示可以通过通过类实例直接访问的信息
- python 第三天(生成器 迭代器 装饰器 序列化)
- day4_装饰器、生成器、迭代器、序列化
- Python生成器、迭代器、装饰器
- Python----装饰器/生成器/迭代器
- python 学习2:生成器,迭代器,装饰器
- Python之装饰器、迭代器和生成器
- 装饰器,生成器,迭代器
- 装饰器、迭代器、生成器
- 迭代器 生成器 装饰器
- python 装饰器 上下文管理器 迭代器 生成器 描述符
- Python高级编程1-闭包,迭代器,装饰器,生成器
- python学习之迭代器、生成器和装饰器
- Python自学笔记九、装饰器,生成器
- python之装饰器与生成器
- Python(基础)第三天
- python学习-Day15-python生成式和生成器、迭代器、装饰器
- 三神器-迭代器、生成器和装饰器
- 闭包,装饰器,迭代器,生成器
- SpringBoot 使用@Aspect进行日志管理(基于反射代理模式)
- 系统管理(一) 查看系统使用情况
- JAVA字符串格式化-String.format()的使用
- CAS Compare and Swap 无锁算法
- eclipse使用技巧---使用正则表达式查找替换
- python 第三天(生成器 迭代器 装饰器 序列化)
- Java SE——引用数据类型
- 1061. 判断题(15)
- 玩转Unity中的ML-Agents 机器学习(一):系统环境安装
- for循环中的一个错误
- 总结一下顶级域名和子级域名之间的cookie共享和相互修改、删除
- 单链表逆序
- 利用php 计算两点地理经纬坐标之间的距离
- 关于Java