大家都知道python中的循環(huán)結(jié)構(gòu),那么我們分析下python中while和for循環(huán)的本質(zhì)是如何實(shí)現(xiàn)的。 循環(huán)的本質(zhì):看以下代碼: lst = [10, 20, 30]# for i in lst: 這個(gè)i的指向其實(shí)指向了 iter(lst)這個(gè)迭代器的__next__my_iterator = iter(lst)while True: try: i = next(my_iterator) except StopIteration: break else: print(i) 原來循環(huán)結(jié)構(gòu)主要應(yīng)用了迭代器功能,而迭代器的實(shí)現(xiàn)主要使用yield函數(shù)。 如何理解python當(dāng)中的yield函數(shù)?若要理解python當(dāng)中的yield函數(shù),首先必須理解什么是生成器(generators),在理解生成器之前必須先理解迭代器(iterators).1、迭代器: 當(dāng)你創(chuàng)建一個(gè)列表list,可以一個(gè)元素一個(gè)元素逐個(gè)讀他,這樣的操作稱為迭代 interation : lst = [10, 20, 30]for i in lst: print(i)102030 這里lst就稱之為一個(gè)可迭代對象,當(dāng)你使用列表推導(dǎo)時(shí)(list comprehension),可以生成一個(gè)列表,列表推導(dǎo)的方法如下所示: >>> mylist = [x*x for x in range(3)]>>> for i in mylist:... print(i)014 所有可以用for ... in ... 操作的對象稱之為可迭代對象,例如字符,列表文件,集合等等。列表這類可迭代對象還比較方便,但缺點(diǎn)就是需要存儲在內(nèi)存中的對象非常多,在值非常多的時(shí)候如果都使用這種方式,就非常占用內(nèi)存。 2、生成器 生成器也是迭代器的一種,是一種只能遍歷一次的可迭代對象。生成器不需要在內(nèi)存當(dāng)中存儲所有的值,他們是即時(shí)生成值,性能更快,關(guān)鍵是不像列表那樣占用太多內(nèi)存。例如: >>> mygenerator = (x*x for x in range(3))>>> for i in mygenerator:... print(i)014 可以看到,除了使用[]替代()之外,其它都是一樣的。 實(shí)際上他們先生成0,然后忘掉0,再生成1,丟棄1,一直往下,一個(gè)接一個(gè)進(jìn)行處理。 3、Yield函數(shù)yield 函數(shù)有點(diǎn)像Return,區(qū)別在于這個(gè)函數(shù)返回的是迭代器.例如: def creGenerator(): mylist = range(3) print('創(chuàng)建生成器') for i in mylist: yield i*imygenerator = creGenerator()for i in mygenerator: print(i) 可以看出來,當(dāng)你知道你的函數(shù)會返回?cái)?shù)量非常大的元素供遍歷時(shí),并且只需讀一次的時(shí)候,使用yield函數(shù)是非常合適的。 若要掌握yield函數(shù),你必須理解當(dāng)你調(diào)用這個(gè)函數(shù)時(shí),函數(shù)內(nèi)部的代碼實(shí)際是沒有執(zhí)行的.這個(gè)函數(shù)只是返回一個(gè)生成器的對象,當(dāng)實(shí)際遍歷時(shí)(for ... in ... ) yield語句才會執(zhí)行。 這里是比較有意思的地方:第一次使用for訪問這個(gè)生產(chǎn)器對象的時(shí)候,' print('創(chuàng)建生成器') '這句話才被打印出來,并且打印在'test'之后,說明yield之前的函數(shù)體會在for第一次循環(huán)時(shí)被調(diào)用一次有且只有調(diào)用一次。但是,如果是這樣情況結(jié)果就不同了: def createGenerator(): mylist = range(3) print('創(chuàng)建生成器') for i in mylist: print 'test3' yield i*i print('test2')mygenerator = createGenerator()print('test')for i in mygenerator: print(i) 可見如果在yield語句同級的代碼塊中的語句,其實(shí)外層for進(jìn)行迭代時(shí),每次都會執(zhí)行。 |
|