Python 迭代器+生成器+装饰器

Python 迭代器+生成器+装饰器,第1张

概述一、迭代器1、迭代器协议迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个stoplteration异常,以终止迭代(只能往后走,不能往前退)协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对 一、迭代器1、迭代器协议迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个stoplteration异常,以终止迭代(只能 往后走,不能往前退)协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象2、可迭代对象

可迭代对象泛指一类对象,不是指的每一种对象,确切的说满足以下的条件的对象可以成为可迭代对象:

对象实现了__iter__方法__iter__方法返回了一个迭代器对象

我们比较容易理解的可迭代对象,比如说可以用for语句去遍历,实际for语句的内部实现应该就是首先调用对象的__iter__方法,获取一个迭代器对象,接着不停的调用迭代器对象的__next__方法,循环遍历取值。

3、迭代器对象(迭代器)

迭代器协议包括这些条件:

对象实现了__next__方法__next__方法返回了某个数值(当然一般情况下,我们需要的是返回这个对象的特定的数字,并且按照一定的顺序进行依次返回)__next__方法需要在值取完的时候,抛出stopiteration的错误信息。

能够迭代的类型:List tuple string set dict bytes迭代器有两个基本的方法:iter() 和 next()

iter返回迭代器对象本身。这用于for 和in语句。next方法返回迭代器中的下一个值。如果没有更多的项目要返回,那么它应该引发stopiteration异常。

创建一个返回数字的迭代器,初始值为 1,逐步递增 1:

class MyNumbers:  def __iter__(self):    self.a = 1    return self   def __next__(self):    x = self.a    self.a += 1    return x myclass = MyNumbers()myiter = iter(myclass) print(next(myiter))print(next(myiter))print(next(myiter))print(next(myiter))print(next(myiter))

输出:

12345
二、生成器

可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己的内置的__iter__方法),所以生成器就是可迭代对象

1、生成器函数

常规函数的定义,但是,使用yIEld语句而不是return语句返回结果。yIEld语句语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行

2、生成器表达式

类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

3、生成器的特点

生成器最大的特点是:边迭代 边输出

Python使用生成器对延迟 *** 作提供了支持。所谓延迟 *** 作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生产层器的主要好处。

 

这里举一个例子来说明生成器的优点

输出斐波那契数列前 N 个数

def fab(max):     n, a, b = 0, 0, 1     L = []     while n < max:         L.append(b)         a, b = b, a + b         n = n + 1     return L for n in fab(5):     print n

该函数在运行中占用的内存会随着参数 max 的增大而增大,如果要控制内存占用,最好不要用 List来保存中间结果,而是通过 iterable 对象来迭代。

class Fab(object):      def __init__(self, max):         self.max = max         self.n, self.a, self.b = 0, 0, 1      def __iter__(self):         return self      def next(self):         if self.n < self.max:             r = self.b             self.a, self.b = self.b, self.a + self.b             self.n = self.n + 1             return r         raise stopiteration() for n in Fab(5):     print n

Fab 类通过 next() 不断返回数列的下一个数,内存占用始终为常数。

然而,使用 class 改写的这个版本,代码远远没有第一版的 fab 函数来得简洁。如果我们想要保持第一版 fab 函数的简洁性,同时又要获得 iterable 的效果,yIEld 就派上用场了:

def fab(max):     n, a, b = 0, 0, 1     while n < max:         yIEld b      # 使用 yIEld        # print b         a, b = b, a + b         n = n + 1 for n in fab(5):     print n

简单地讲,yIEld 的作用就是把一个函数变成一个 generator,带有 yIEld 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(i) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yIEld b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yIEld b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yIEld。

 

一个带有 yIEld 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yIEld 语句就会中断,并返回一个迭代值,下次执行时从 yIEld 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yIEld 中断了数次,每次中断都会通过 yIEld 返回当前的迭代值。

yIEld 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰。

这里记录一个引出本篇博客的问题:

Scrapy中yIEld的理解

https://www.oschina.net/question/2254016_238539

 

三、装饰器 总结

以上是内存溢出为你收集整理的Python 迭代器+生成器+装饰器全部内容,希望文章能够帮你解决Python 迭代器+生成器+装饰器所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1183626.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存