可迭代对象泛指一类对象,不是指的每一种对象,确切的说满足以下的条件的对象可以成为可迭代对象:
对象实现了__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 迭代器+生成器+装饰器所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)