python生成器函数_自学Python4.7-生成器(方式一:生成器函数)

自学Python4.7 - 生成器(方式一:生成器函数)

定义:生成器(generator)是一个包含yield关键字的函数,当它被调用的时候,在函数体中的代码不会被执行,而是会返回一个迭代器。

(一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator);

如果函数中包含yield语法,那这个函数就会变成生成器;)

生成器是一个特殊的程序,可以被用作控制循环的迭代行为

生成器类似于返回值为数组的一个函数,这个函数可以接收参数,可以被调用,但是,不同于一般的函数会一次性返回包含了所有数值的数组,生成器一次 只产生一个值,这样消耗的内粗数量大大减少,而且允许调用函数可以很快的开始处理前几个返回值。因此,生成器看起来像一个函数但是表现的却像一个迭代器

python提供了两种基本的生成器方式:

生成器函数:也是用def来定义,利用关键字yield一次返回一个结果,阻塞,重新开始

每次请求一个值,就会执行生成器中的代码,知道遇到一个yield或者return语句

①yield语句意味着应该生成一个值

②return语句意味着要停止执行(不生成任何东西,只有在一个生成器中使用时才能进行无参数调用)

生成器表达式:返回一个对象,这个对象只有在需要的时候才产生结果

1. 生成器函数:

为什么叫生成器函数?因为他随着时间的推移生成了一个数值队列。一般的函数在执行完毕之后会返回一个值然后退出,但是生成器函数会自动挂起,然后重新拾起继续执行,他会利用yield关键字关起函数,给调用者返回一个值,同时保留了当前的足够多的状态,可以使函数继续执行。

生成器和迭代协议是密切相关的,可迭代的对象都有一个__next()__成员方法,这个方法要么返回迭代的下一项,要么引起异常结束迭代。

为了支持迭代协议,拥有yield语句的函数被编译为生成器,这类函数被调用时返回一个生成器对象,返回的对象支持迭代接口,即成员方法__next()__继续从中断处执行执行。

def func(): #func是函数称为生成器,当执行此函数func()时会得到一个迭代器。

yield 1

yield 2

yield 3

yield 4

temp = func()

print(temp.__next__())

print(temp.__next__())

print(temp.__next__())

print(temp.__next__())

1217531-20190325090328300-1797360726.png

def creat_counter(n):

print('create counter')

while True:

yield n

print('increment n')

n += 1

cnt = creat_counter(2)

print(cnt)

print(next(cnt))

print(next(cnt))

print(next(cnt))

1217531-20190325090422256-785627743.png

分析以上的列子:

在create_counter函数中出现了关键字yield,预示着这个函数每次只产生一个结果值,这个函数返回一个生成器(通过第一行输出可以看出来),用来产生连续的n值

在创造生成器实例的时候,只需要像普通函数一样调用就可以,但是这个调用却不会执行这个函数,这个可以通过输出看出来

next()函数将生成器对象作为自己的参数,在第一次调用的时候,他执行了create_counter()函数到yield语句,返回产生的值2

我们重复的调用next()函数,每次他都会从上次被挂起的地方开始执行,直到再次遇到了yield关键字

def cube(n):

for i in range(n):

yield i ** 3

for i in cube(5):

print(i)

1217531-20190325090602975-859756820.png

从理解函数的角度出发我们可以将yield类比为return,但是功能确实完全不同,在for循环中,会自动遵循迭代规则,每次调用next()函数,所以上面的结果不难理解。

举例1:

1217531-20190321205337794-2085145858.png

举例2:

1217531-20190321205254312-1627438104.png

举例3: 取不到值会报错

1217531-20190321205640024-1856943485.png

举例4: 使用for循环取值

1217531-20190321205801095-1423660531.png

举例5.1 : 打印出10个哇哈哈

1217531-20190321210125776-1606685308.png

举例5.2 :如果现在有10个哇哈哈, 我现在只想用5个

1217531-20190321210443012-1590461814.png

迭代器依旧延续向下走:

1217531-20190321210651886-2001838569.png

举例6:

def generator():

print('123')

content = yield 1

print('=========',content)

print(456)

yield 2

g = generator()

ret = g.__next__()

print("******",ret)

ret = g.send("hello")

print("**********",ret)

1217531-20190325100756190-615099876.png

send 获取下一个值的效果和next基本一致,只是在获取下一个值得时候,给上一个yield的位置传递一个数据

使用send的注意事项:

第一次使用生成器的时候,是用next获取下一个值

函数最后一个yield不能接受外部的值

举例7.1:获取移动平均值:

10 20 30 10

15 20 17.5

1217531-20190325114751922-1860284810.png

def average():

sum = 0

count = 0

avg = 0

while True:

num = yield avg

sum += num

count += 1

avg = sum/count

avg_g = average()

avg_g.__next__()

avg1 = avg_g.send(10)

avg1 = avg_g.send(20)

avg1 = avg_g.send(30)

print(avg1)

1217531-20190325115604097-1719381358.png

举例7.2: 预激生成器的装饰器完成获取移动平均值

def init(func): #装饰器

def inner(*args,**kwargs):

g = func(*args,**kwargs) #g = average()

g.__next__()

return g

return inner

@init

def average():

sum = 0

count = 0

avg = 0

while True:

num = yield avg

sum += num # 10

count += 1 # 1

avg = sum/count

avg_g = average() #===> inner

ret = avg_g.send(10)

print(ret)

ret = avg_g.send(20)

print(ret)

以上程序执行步骤:

1217531-20190325121235246-1840525353.png

1217531-20190325121222317-1987743136.png

举例8 :

在python3里面的新功能 yield from

1217531-20190325123916494-221499273.png

1217531-20190325123957038-935439145.png

.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中,生成器函数是一种特殊类型的函数,它使用 yield 关键字来返回一个迭代器。生成器函数可以用于按需生成值,而不是一次性生成所有值。 生成器函数的定义与普通函数类似,但使用 yield 语句而不是 return 语句来返回值。当调用生成器函数时,它会返回一个生成器对象,而不会立即执行函数体。每次迭代生成器对象时,函数会从上次暂停的位置继续执行,并返回 yield 语句后的值,直到没有更多的 yield 语句为止。 下面是一个简单的生成器函数示例,用于生成斐波那契数列: ```python def fibonacci(): a, b = 0, 1 while True: yield a a, b = b, a + b fib = fibonacci() for i in range(10): print(next(fib)) ``` 在上面的例子中,定义了一个名为 fibonacci 的生成器函数。它使用 while 循环和 yield 语句来生成斐波那契数列中的每个值。每次调用 next() 函数时,生成器会从上次暂停的位置继续执行,并返回 yield 语句后的值。 通过调用 fibonacci() 函数,我们得到了一个生成器对象 fib。然后使用 for 循环和 next() 函数迭代该生成器对象,打印出斐波那契数列的前 10 个数。 输出结果为: ``` 0 1 1 2 3 5 8 13 21 34 ``` 生成器函数的优点是它们可以按需生成值,而不需要一次性生成所有值,这在处理大量数据或无限序列时非常有用。由于生成器函数的特殊性质,它们具有较低的内存消耗,并且可以以一种更高效的方式实现迭代逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值