生成器

本文详细介绍了Python中的生成器概念,包括生成器的定义、如何创建生成器、生成器与普通函数的区别,以及如何使用生成器的__next__()和send()方法。通过具体的代码示例,帮助读者更好地理解和掌握生成器的使用。

如果一个函数返回的是迭代器,那么这个函数就被称为生成器(generator),一个函数如果使用yield关键字返回或接收值,那么这个函数就是生成器。

def gen():
    yield 1
a = gen()
print(a.__next__())
print(type(a))
-----------------------------------
1
<class 'generator'>

使用列表生成式会生成一个list,但将列表生成式的[]替换成()后,返回的就是generator

>>> type([ x for x in range(5)])
<class 'list'>
>>> type((x for x in range(5)))
<class 'generator'>

 生成器对象也是一个迭代器对象,可以使用__next__()函数来迭代数据

>>> gen = (x for x in range(5))>>> gen.__next__()
0
>>> gen.__next__()
1
>>> gen.__next__()
2

我们分别使用return关键字和yield关键字看一下两者的区别

def gen():
    print("这是一行输出")
    return 1
    #yield 1
a = gen()
print("a=",a)
-------------------------

这是一行输出
a= 1

def gen():
    print("这是一行输出")
    #return 1
    yield 1
a = gen()
print("a=",a)
----------------------------------
a= <generator object gen at 0x01194F00>

可以看到,当用一个变量接收一个一个函数时,会将函数的返回值赋给变量,并且会执行整个函数,而使用yield关键字时,函数的内部不会执行,并且返回的是一个生成器,需要使用__next__()方法才能将yield后的值返回出来,再例如:

>>> def gen():
...     print("这是第一行输出")
...     yield 1
...     print("这是第二行输出")
...     yield 2
...
>>> a = gen()
>>> a.__next__()
这是第一行输出
1
>>> a.__next__()
这是第二行输出
2

可以看到,当使用变量接收一个生成器时,与函数不同,生成器里的内容都不会被执行,只有使用__next()__后,生成器才会开始执行,并在遇到yield时停止,当函数已经执行完后使用__next__()函数就会报出StopIteration的异常,我们接上面的代码执行__next__()函数,如下:

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

生成器的作用就是为了在数据量比较大的情况节省空间,一般是在生成大量数据时使用,所以一般会与where循环一起使用,一种常用的生成器的定义方式应该是:

def num():
    n = 0
    while True:
        yield n
        n +=1
        if n > 10:
            break
i = num()
while True:
    try:
        print(i.__next__())
    except StopIteration:
        break

如迭代器一样,遍历生成器时可以使用try...except...来接收StopIteration异常,当然也可以将生成器对象作为普通的迭代器对象来使用for循环遍历:

def num():
    n = 0
    while True:
        yield n
        n +=1
        if n > 10:
            break
i = num()
for a in i:
        print(a)

两种方式输出的结果一致。

生成器中除了可以使用__next__()方法获取生成器生成的数据外,还可以使用send()方法像生成器中传值:

def sum():
    n = 0
    while True:
        a = yield n
        print("a = ",a)
        n = a+n
s = sum()
print(s.__next__())
print(s.send(2))
-------------------------------

0
a = 2
2

__next__()函数等同于send(None),生成器中所有使用__next__()的地方都可以使用send(None)代替,生成器第一次执行时是从函数开始的地方执行,因为没有值获取yield传来的值,所以第一次执行时必须使用__next__()或者参数是‘None’的send()方法。从上面的输出可以看出执行send()方法时先执行 "a = yield"然后执行其他代码,最后才会执行"yiled n"然后结束

 

只需要熟练的运用__next__()和send()方法,了解yield的机制,对于生成器的使用就不会有什么问题了

 

转载于:https://www.cnblogs.com/princeYQ/p/8484900.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值