Python高级特性之迭代器、生成器、装饰器和上下文管理器

今天测试Python高级特性-迭代器、生成器、装饰器、上下文管理器。高级语言特性可以使得程序更加Pythonic,可读性、可维护性显著增加。下面四个高级特性,笔者在收集资料以及用ipython测试。装饰器的只是测试基本的功能,笔者觉得有点复杂。

1、迭代器

 迭代器协议是指:对象需要提供next方法,要么返回迭代中的下一项,要么就引起一个StopIteration异常以终止迭代,防止出现无限循环的情况。迭代器是一个可以记住遍历的位置的对象。

迭代器有两个基本的方法:iter() 和 next()。字符串,列表或元组对象都可用于创建迭代器:

迭代器对象可以使用常规for语句(使用迭代器协议访问对象)进行遍历:

文件对象在python中实现了迭代器协议,有next方法,可以很方便的访问文件中的内容。

也可以自己创建一个迭代器,下面时笔者根据资料来创建的一个打印20位数值的迭代器。把类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。

__iter__() 方法返回一个特殊的迭代器对象,在 __next__() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。


2、生成器       

生成器自动实现了迭代器协议。使用了 yield 的函数被称为生成器,跟普通函数不同的是,生成器是一个返回迭代器的函数。在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。调用一个生成器函数,返回的是一个迭代器对象。

python有两种方法来提供生成器。

2.1 生成器函数

使用yield 语句而不是return返回结果。函数就是一个实现了迭代器协议的函数,可以直接使用for来遍历。

2.2 生成器表达式

将列表推导中的中括号换成圆括号就是生成器表达式。squares_list是个列表推导,返回的是个列表。squares使用生成器表达式,返回的是个生成器对象generator object ,由于生成器自动实现了迭代器协议,使用for循环迭代输出。

生成器可以延迟计算,一次返回一个结果,而不是一次返回使用结果,对于大数据量处理十分有用。

3、装饰器

装饰器本质上是个函数,这个函数接收其他函数作为参数。下面是定义bread装饰器修改say_hi函数的功能,即使用bread函数来封装say_hi函数,@是装饰器语法,bread是装饰器的名称。

在实际应用中,可以将重复的代码提炼出来作为一个单独的函数,然后做成装饰器,可以提高代码的可读性,代码量也会更少,也降低后期维护代价。下面是定义的计算函数计算时间的benchmark装饰器,然后在加法和减法函数里面使用benchmark装饰器来封装。

但是装饰器的语法较复杂,执行速度也较慢和难以调试。

4、上下文管理器

with 上下文管理器的作用与try/finally语句作用类似,在确保打开的资源在任何情况下都能关闭。在python在python中优先使用上下文管理器,可以用更少的代码完成相同的功能,而且逻辑更加清除。

with语句的表达式返回一个对象,该对象必须有__enter__和__exit__方法。上面的第一部分打开文件后文件对象在python中实现了迭代器协议,有next方法,也有__enter__和__exit__方法,可以使用 with 上下文管理器:with open('data.csv') as f 。

上下文管理器可以以一种更加优雅的方式,操作(创建/获取/释放)资源,如文件操作、数据库连接,并且处理异常。下面是自己定义上下文管理器,含有__enter__和__exit__方法的对象Resource。

在上面吃的例子中,写了一个类来构建上下文管理器。可以使用contextlib 来简化上下文管理器的逻辑,其提供了contextmanager的装饰器,通过该装饰器装饰的函数就成为一个上下文管理器,可以用在with语句中。

在被装饰函数里,必须是一个生成器(带有yield),而yield之前的代码,就相当于__enter__里的内容。yield 之后的代码,就相当于__exit__ 里的内容。下面是自己来定义一个open_func函数,使用contextmanager来装饰成上下文管理器,yield之前的代码时打开文件,yield之后的代码是关闭文件。

上面这段代码只能实现上下文管理器的第一个目的(管理资源),并不能实现第二个目的(处理异常)。可以使用try + except+finally来实现异常处理。

在实际中,可能不需要except来抛出异常,只是用try + finally。下面是以前做过的将连接数据库的功能使用contextmanager来装饰成上下文管理器。

在上下文管理器中,with语句可以使用逗号隔开,同时使用多个上下文管理器。

作者:刘小白DOER
链接:https://www.jianshu.com/p/211276cbfd9d
来源:简书

推荐阅读

一文看懂Python协程asyncio模块的演变及高级用法

正确使用Python f-string格式化字符串的7个层级

一文看懂Python collections模块的高效数据类型

一文看懂Python系列之装饰器(decorator)(工作面试必读)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值