迭代器(Iterator)python
为了理解yield是什么,首先要明白生成器(generator)是什么,在讲生成器以前先说说迭代器(iterator),当建立一个列表(list)时,你能够逐个的读取每一项,这就叫作迭代(iteration)。函数
例子:工具
>>> mylist = [1,2,3,4] >>> for i in mylist : ... print i ... 1 2 3 4
Mylist就是一个迭代器,无论是使用复杂的表达式列表,仍是直接建立一个列表,都是可迭代的对象。对象
>>> mylist = [x*x for x in range(3)] list推导式 >>> for i in mylist : ... print i ... 0 1 4
你可使用“for··· in ···”来操做可迭代对象,如:list,string,files,这些迭代对象很是方便咱们使用,由于你能够按照你的意愿进行重复的读取。可是你不得不预先存储全部的元素在内存中,那些对象里有不少元素时,并非每一项都对你有用。blog
生成器(Generators)接口
生成器一样是可迭代对象,可是你只能读取一次,由于它并无把全部值存放内存中,它动态的生成值:ip
>>> mylist = [x*x for x in range(3)] list推导式 >>> for i in mylist : ... print i ... 0 1 4
使用()和[]结果是同样的,可是,第二次执行“ for in mygenerator”不会有任何结果返回,由于它只能使用一次。首先计算0,而后计算1,以后计算4,依次类推。内存
Yieldgenerator
Yield是关键字, 用起来像return,yield在告诉程序,要求函数返回一个生成器。string
>>> def createGenerator(): ... mylist = range(3) ... for i in mylist: ... yield i * i ... >>> mygenerator = createGenerator() >>> print mygenerator <generator object createGenerator at 0x7fd61e8ba190> >>> for i in mygenerator: ... print i ... 0 1 4
这个示例自己没什么意义,可是它很清晰地说明函数将返回一组仅能读一次的值,要想掌握yield,首先必须理解的是:当你调用生成器函数的时候,如上例中的createGenerator(),程序并不会执行函数体内的代码,它仅仅只是返回生成器对象,这种方式颇为微妙。函数体内的代码只有直到每次循环迭代(for)生成器的时候才会运行。
函数第一次运行时,它会从函数开始处直到碰到yield时,就返回循环的第一个值,而后,交互的运行、返回,直到没有值返回为止。若是函数在运行可是并无遇到yield,就认为该生成器是空,缘由多是循环终止,或者没有知足任何”if/else”
>>> class Bank(): # 建立银行,构造ATM机 ... crisis = False ... def create_atm(self) : ... while not self.crisis : ... yield "$100" >>> hsbc = Bank() # 没有危机时,你想要多少,ATM就能够吐多少 >>> corner_street_atm = hsbc.create_atm() >>> print(corner_street_atm.next()) $100 >>> print(corner_street_atm.next()) $100 >>> print([corner_street_atm.next() for cash in range(5)]) ['$100', '$100', '$100', '$100', '$100'] >>> hsbc.crisis = True # 危机来临,银行没钱了 >>> print(corner_street_atm.next()) <type 'exceptions.StopIteration'> >>> wall_street_atm = hsbc.ceate_atm() # 新建ATM,银行仍然没钱 >>> print(wall_street_atm.next()) <type 'exceptions.StopIteration'> >>> hsbc.crisis = False # 麻烦就是,即便危机事后银行仍是空的 >>> print(corner_street_atm.next()) <type 'exceptions.StopIteration'> >>> brand_new_atm = hsbc.create_atm() # 构造新的ATM,恢复业务 >>> for cash in brand_new_atm : ... print cash $100 $100 $100 $100 $100 $100 $100 $100 $100
迭代工具,你最好的朋友
迭代工具模块包含了操作指定的函数用于操做迭代器。想复制一个迭代器出来?连接两个迭代器?以one liner(这里的one-liner只需一行代码能搞定的任务)用内嵌的列表组合一组值?不使用list建立Map/Zip?···,你要作的就是 import itertools,举个例子吧:
四匹马赛跑到达终点排名的全部可能性:
>>> hroses = [1,2,3,4] >>> races = itertools.permutations(hroses) >>> print races <itertools.permutations object at 0x7fd61e893890> >>> print (list(itertools.permutations(hroses))) [(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)] >>>
理解迭代的内部机制:
迭代(iteration)就是对可迭代对象(iterables,实现了__iter__()方法)和迭代器(iterators,实现了__next__()方法)的一个操做过程。可迭代对象是任何可返回一个迭代器的对象,迭代器是应用在迭代对象中迭代的对象,换一种方式说的话就是:iterable对象的__iter__()方法能够返回iterator对象,iterator经过调用next()方法获取其中的每个值(译者注),读者能够结合Java API中的 Iterable接口和Iterator接口进行类比。