天天看點

生成器 python0 1 8 27 64_python -- 生成器

在for循環中,每次yield值後,控制權就傳回給for循環

生成器類似于傳回一個數組的函數。生成器有參數、可以被調用,并生成值的序列。和函數一次傳回整個數組不同,生成器每次隻是生成一個值,這樣會占用很少的記憶體,并且調用者可以立即處理生成的值。概括來說,生成器看起來像個函數,但是使用起來像個疊代器。

Python提供的,在需要時才生成結果的工具:

-生成器函數:

使用def定義,但是每次使用yield生成傳回值值、挂起、在繼續運作。

-生成器表達式:

類似于清單推導,但不是建立一個結果清單,而是每次根據需要生成對象。

因為無論是生成器函數、還是生成器表達式都不是一次生成一個結果清單,這樣可以節省記憶體空間,并将計算時間以疊代協定的方式切分開。

生成器函數:yield和return

生成器函數和正常函數有點類似,都是使用def定義。當建立後,自動實作疊代協定。

正常函數會傳回值并退出。而疊代器函數傳回一個值後會自動挂起、然後再次執行。

生成器函數和正常函數之間的主要差別是前者yield一個值,後者傳回一個值。yield會挂起函數,傳回一個值給調用者。

生成器是和疊代協定綁在一起的。可疊代的對象定義一個方法:__next__(),該方法要麼傳回疊代器的下一個值,要麼抛出一個異常。

定義生成器的時候需要使用關鍵字:yield。

讓我們來看個示例:

>>> def counter(n):

print("counter()")

while True:

yield n

print("increment n")

n += 1

>>> c = counter(2)

>>> c

>>> next(c)

counter()

2

>>> next(c)

increment n

3

>>> next(c)

increment n

4

>>> c.next()

increment n

5

>>> c.next()

increment n

6

>>>

1.關鍵字yield表明該函數不是一個正常函數,而是一個疊代器函數。

2.生成一個疊代器的執行個體,和調用正常函數類似。但是調用的時候并不真正執行函數代碼。

3.counter()傳回一個疊代器對象

比如,下面的疊代器生成數字的立方值

>>> def cubic_generator(n):

for i in range(n):

yield i**3

>>> cg = cubic_generator(3)

>>> cg

>>> cg.next()

>>> cg.next()

1

>>> cg.next()

8

>>> cg.next()

Traceback (most recent call last):

File "", line 1, in

cg.next()

StopIteration

>>>

在for循環中,每次yield值後,控制權就傳回給for循環:

>>> for i in cubic_generator(5):

print(i)

1

8

27

64

>>>

如果用return代替yield:

>>> def cubic_generator(n):

for i in range(n):

return i**3

>>> for i in cubic_generator(5):

print(i)

Traceback (most recent call last):

File "", line 1, in

for i in cubic_generator(5):

TypeError: 'int' object is not iterable

>>> cubic_generator(5)

>>>

使用生成器的示例1:

>>> def fib():

limit = 10

count = 0

a,b = 0,1

while True:

yield a

a,b = b,a+b

if (count == limit):

break

count += 1

>>> for i in fib():

print(i)

1

1

2

3

5

8

13

21

34

55

>>>

使用生成器實作斐波納契數列:

>>> def fib(max):

a,b = 0,1

while a < max:

yield a

a,b = b,a+b

>>> for i in fib(500):

print (i)

1

1

2

3

5

8

13

21

34

55

89

144

233

377

>>> list(fib(500))

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]

>>>

生成器表達式: 可推導的疊代器

疊代器和清單推導相結合,形成了一個新特性:生成器表達式。

生成器表達式和清單表達式類似,但是前者被小括号包含着,後者是用方括号包含的。

>>> #清單推導

>>> [x**3 for x in range(5)]

[0, 1, 8, 27, 64]

>>>

>>> #生成器表達式

>>> (x**3 for x in range(5))

at 0x0000000002BE0798>

>>>

>>> list(x**3 for x in range(5))

[0, 1, 8, 27, 64]

>>>

>>> gen=(x**3 for x in range(5))

>>> gen.next()

>>> gen.next()

1

>>> gen.next()

8

>>> gen.next()

27

>>> gen.next()

64

>>> gen.next()

Traceback (most recent call last):

File "", line 1, in

gen.next()

StopIteration

>>>

生成器:函數 vs 表達式

相同的疊代可以用生成器函數或生成器表達式實作。二者都可以自動疊代或手動疊代。

>>> gen = (c*5 for c in 'pyhton')

>>> list(gen)

['ppppp', 'yyyyy', 'hhhhh', 'ttttt', 'ooooo', 'nnnnn']

>>>

>>> def gen(x):

for c in x:

yield c*5

>>> g=gen('python')

>>> list(g)

['ppppp', 'yyyyy', 'ttttt', 'hhhhh', 'ooooo', 'nnnnn']

>>>