国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

迭代器與生成器

2019-11-08 02:26:05
字體:
供稿:網(wǎng)友

一、迭代器

數(shù)學(xué)中的迭代可以指函數(shù)迭代的過程,即反復(fù)地運(yùn)用同一函數(shù)計(jì)算,前一次迭代得到的結(jié)果被用于作為下一次迭代的輸入。 即使是看上去很簡(jiǎn)單的函數(shù),在經(jīng)過迭代之后也可能產(chǎn)生復(fù)雜的行為,衍生出具有難度的問題。——引自維基百科

0. 迭代器協(xié)議

  __iter__()next()這兩個(gè)方法一起構(gòu)成了迭代器協(xié)議。即滿足了這個(gè)兩個(gè)方法才能稱之為迭代器。

1. 可迭代的對(duì)象

  在Python中一樣也有迭代的概念。比如循環(huán)打印出列表中的元素,這就是一個(gè)迭代的過程。在Python中,不僅可以對(duì)列表、元組、字典等進(jìn)行迭代,還可以對(duì)其他對(duì)象迭代,前提是這個(gè)對(duì)象實(shí)現(xiàn)了 __iter__方法,這個(gè)對(duì)象也稱為可迭代的對(duì)象。

2. 迭代器

  具有next方法的的可迭代對(duì)象iter方法會(huì)返回一個(gè)迭代器(__iter__返回的是迭代器本身)。在調(diào)用next方法時(shí),迭代器會(huì)返回它的下一個(gè)值,如果next方法調(diào)用后,但是又沒有值返回,就會(huì)引發(fā)StopIteration異常。

3. 示例1

>>> lists = [i for i in range(10)]# 可迭代的對(duì)象還有__iter__方法>>> dir(lists)['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__',........]# 獲得迭代器>>> iters = lists.__iter__()>>> for i in range(len(lists)):... PRint iters.next(), ... 0 1 2 3 4 5 6 7 8 9

如果繼續(xù)調(diào)用,就會(huì)引發(fā)StopIteration異常

>>> iters.next()Traceback (most recent call last): File "<stdin>", line 1, in <module>StopIteration

內(nèi)建函數(shù)iter()可以從可迭代的對(duì)象中獲得迭代器;list()含糊可以將迭代器顯示的以列表的形式打印

>>> test = [i for i in range(5)]>>> iters = iter(test)>>> list(iters)[0, 1, 2, 3, 4]

4. 示例2—自定義迭代器

#!/usr/bin/pythonclass Fibs: value = 0 def __init__(self,ranges): self.ranges = ranges def next(self): self.value += 1 if self.value == self.ranges: raise StopIteration return self.value def __iter__(self): return selfIn [7]: from iters import FibsIn [8]: fib = Fibs(10)In [9]: list(fib)Out[9]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

接下來驗(yàn)證是否為迭代器

In [2]: from iters import FibsIn [3]: from collections import Iterator In [4]: from collections import Iterable # 是迭代器對(duì)象In [5]: isinstance(iter(Fibs(10)), Iterator)Out[5]: True#可迭代的對(duì)象In [6]: isinstance(iter(Fibs(10)), Iterable)Out[6]: True

注釋掉next()方法

#!/usr/bin/pythonclass Fibs: value = 0 def __init__(self,ranges): self.ranges = ranges #def next(self): #self.value += 1 #if self.value == self.ranges: raise StopIteration #return self.value def __iter__(self): return self

此時(shí)結(jié)果如下,沒有next()方法就不再是iterator了:

In [3]: from iters import Fibs#是可迭代的對(duì)象In [4]: isinstance(iter(Fibs(10)), Iterable)Out[4]: TrueIn [5]: from collections import Iterator#不是迭代器對(duì)象In [6]: isinstance(iter(Fibs(10)), Iterator)Out[6]: False

二、生成器

A function which returns an iterator. It looks like a normal function except that it contains yield statements for producing a series a values usable in a for-loop or that can be retrieved one at a time with the next() function. Each yield temporarily suspends processing, remembering the location execution state (including local variables and pending try-statements). When the generator resumes, it picks-up where it left-off (in contrast to functions which start fresh on every invocation).

生成器是一個(gè)函數(shù)(任何包含yield語句的函數(shù)就是生成器)這個(gè)函數(shù)的返回值是迭代器yield語句功能是為了在for循環(huán)中產(chǎn)生一系列的值;或者是使用next()一次檢索一個(gè)值每次產(chǎn)生一個(gè)值,函數(shù)就會(huì)被凍結(jié):即函數(shù)停在那點(diǎn)等待被重新喚醒。函數(shù)被重新喚醒后就從停止的那點(diǎn)開始執(zhí)行。

定義生成器的兩種方式: - yield聲明 - 生成器表達(dá)式

1. yield語句

In [57]: def sums(ranges): ....: test = 0 ....: for i in range(ranges): ....: test += i ....: yield test ....: # next()方法一次檢索一個(gè)值In [58]: sums(10).next()Out[58]: 0In [59]: sums(10).next()Out[59]: 0#for循環(huán)產(chǎn)生一系列的值In [60]: for i in sums(10): ....: print i, ....: 0 1 3 6 10 15 21 28 36 45In [61]: sums(10)Out[61]: <generator object sums at 0x20ca190>

2. 生成器表達(dá)式

生成器表達(dá)式返回的是生成器;生成器定義的方法類似于列表推導(dǎo)式,但是生成器用的是圓括號(hào);list()方法可以把生成器以列表的形式顯示出來;

In [53]: g = (i for i in range(10))In [54]: gOut[54]: <generator object <genexpr> at 0x20c5eb0>In [55]: list(g)Out[55]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

生成器表達(dá)式也可以在當(dāng)前的圓括號(hào)內(nèi)直接使用。比如在函數(shù)調(diào)用中就不需要增加另外一個(gè)圓括號(hào)了。 如果需要生成大量的的值再迭代計(jì)算,最好不要使用列表推導(dǎo)式,而是使用生成器推導(dǎo)式直接迭代。因?yàn)榱斜硗茖?dǎo)式會(huì)實(shí)例化一個(gè)列表,從而喪失迭代的優(yōu)勢(shì)。

In [50]: sum(i for i in range(10)) Out[50]: 45

3. 生成器表達(dá)式和列表推導(dǎo)式的性能對(duì)比

In [41]: time sum([i for i in range(10000000)])CPU times: user 0.49 s, sys: 1.79 s, total: 2.28 sWall time: 2.28 sOut[41]: 49999995000000In [42]: time sum(i for i in range(10000000)) CPU times: user 0.65 s, sys: 0.00 s, total: 0.65 sWall time: 0.64 sOut[42]: 49999995000000

通過這個(gè)例子可以看出,在大量數(shù)據(jù)迭代的情況下,生成器表達(dá)式比列表推導(dǎo)式的性能好。因?yàn)榱斜硗茖?dǎo)式實(shí)實(shí)在在的生成了一個(gè)列表,在這里個(gè)例子中,先生成列表再求和,已經(jīng)是2層for循環(huán)了,自然就要慢一點(diǎn)了。

通過這個(gè)例子順便再對(duì)比一下xrange()和range()的性能吧

In [62]: time sum(i for i in xrange(10000000)) CPU times: user 0.50 s, sys: 0.00 s, total: 0.50 sWall time: 0.50 sOut[62]: 49999995000000In [63]: time sum(i for i in range(10000000)) CPU times: user 0.59 s, sys: 0.60 s, total: 1.19 sWall time: 1.19 sOut[63]: 49999995000000
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 伊宁县| 托克逊县| 平潭县| 中牟县| 新晃| 油尖旺区| 商都县| 通化县| 城固县| 会泽县| 缙云县| 砚山县| 屯门区| 岑溪市| 茂名市| 西盟| 祁阳县| 雅江县| 会东县| 华安县| 永福县| 探索| 乳山市| 岫岩| 莱西市| 通海县| 定边县| 沙雅县| 玛沁县| 都江堰市| 铜梁县| 康定县| 满洲里市| 松江区| 融水| 舞钢市| 仁布县| 舟山市| 龙海市| 东乌| 咸丰县|