Python:yield关键字以及next、send函数的作用

yield与生成器

def func(n):
    for i in range(0, n):
        print('func: ', i)
        # yield i

f = func(10)
程序执行结果
func:  0
func:  1
func:  2
func:  3
func:  4
func:  5
func:  6
func:  7
func:  8
func:  9
当我们把注释去掉后:
def func(n):
    for i in range(0, n):
        print('func: ', i)
        yield i

f = func(10)
程序没有任何输出。
输出此函数:
print(func(10))
得到
<generator object func at 0x0000004B57353A98>

我们得出以下结论:
1、带有yield关键字的函数自动变成生成器
2、生成器被调用时不会立即执行
那么,怎么获得生成器的生成的值呢
使用next函数:
import time
def func(n):
    for i in range(0, n):
        print('func: ', i)
        yield i

f = func(10)
while True:
    print(next(f))
    time.sleep(1)
程序输出:
func:  0
0
func:  1
1
func:  2
2
func:  3
3
func:  4
4
func:  5
5
func:  6
6
func:  7
7
func:  8
8
func:  9
9
Traceback (most recent call last):
  File "C:/Users/mingC/PycharmProjects/pro_test/Demo/Demo4.py", line 9, in <module>
    print(next(f))
StopIteration

结论:
1、对于生成器,当调用函数next(generator)时,将获得生成器yield后面表达式的值;
2、当生成器已经执行完毕时,再次调用next函数,生成器会抛出StopIteration异常

扩展:
1、当生成器内部执行到return语句时,自动抛出StopIteration异常,return的值将作为异常的解释
2、外部可以通过generator.close()函数手动关闭生成器,此后调用next或者send方法将抛出异常

next与send函数

next函数与send函数很相似,都能获得生成器的下一个yield后面表达式的值,不同的是 send函数可以向生成器传参
import time
def func(n):
    for i in range(0, n):
        arg = yield i
        print('func:', arg)

f = func(10)
while True:
    print('main:', next(f))
    print('main:', f.send(100))
    time.sleep(1)
输出结果:
main: 0
func: 100
main: 1
func: None
main: 2
func: 100
main: 3
func: None
main: 4
func: 100
main: 5
func: None
main: 6
func: 100
main: 7
func: None
main: 8
func: 100
main: 9
Traceback (most recent call last):
func: None
  File "C:/Users/mingC/PycharmProjects/pro_test/Demo/Demo4.py", line 9, in <module>
    print('main:', next(f))
StopIteration

程序首先调用next函数,使得生成器执行到第4行的时候, 把i的值0作为next函数的返回值返回,程序输出main:0,然后生成器暂停。程序往下调用send(100)函数,
生成器从第四行继续执行, send函数的参数100作为yield的返回值,并赋值给arg,然后得到func:100的输出。
简单的说,send函数使得yield关键字拥有了返回值返回给它的左值。

常见错误

import time
def func(n):
    for i in range(0, n):
        arg = yield i
        print('func:', arg)

f = func(10)
while True:
    print('main:', f.send(100))
    time.sleep(1)
输出:
Traceback (most recent call last):
  File "C:/Users/mingC/PycharmProjects/pro_test/Demo/Demo4.py", line 9, in <module>
    print('main:', f.send(100))
TypeError: can't send non-None value to a just-started generator
错误说明显示: 不能将一个非None的值传给初始的生成器

从上面的测试,我们知道,当调用send函数前,生成器内部应该执行到yield所在的语句并暂停。而在这次的测试中,我们从一开始就调用send并传了一个参数,
程序报错误。
因此,在调用带非空参数的send函数之前,我们应该 使用next(generator)或者send(None)使得生成器执行到yield语句并暂停。
import time
def func(n):
    for i in range(0, n):
        arg = yield i
        print('func:', arg)

f = func(5)
print('main:', f.send(None))
while True:
    print('main:', f.send(100))
    time.sleep(1)
输出结果:
main: 0
func: 100
main: 1
func: 100
main: 2
func: 100
main: 3
func: 100
main: 4
func: 100
Traceback (most recent call last):
  File "C:/Users/mingC/PycharmProjects/pro_test/Demo/Demo4.py", line 10, in <module>
    print('main:', f.send(100))
StopIteration

关于yield from

yield from 用于生成器的嵌套。详细解释可以看这篇博文:http://blog.theerrorlog.com/yield-from-in-python-3.html

奋斗这是我写的第一篇博文,虽然知识点不多,但是也是对自己学习的一个小总结,希望以后能够坚持将自己编程路上的所思所想写到这里,感谢认真观看这篇博文的朋友们。
Python中,`yield`关键字用于定义生成器函数生成器函数是一种特殊的函数,它可以产生一个迭代器对象,通过迭代器可以逐步产生值而不是一次性返回所有结果。生成器函数使用`yield`语句来指示函数在每次被调用时暂停执行,并返回一个值给调用者。调用者可以通过调用生成器的`next()`方法或使用`for`循环来逐步获取生成器产生的值。 除了在生成器函数中使用`yield`语句来控制生成器的执行流程外,`yield`还可以与其他语句和表达式一起使用,例如`send()`方法可以在生成器中发送一个值,并将其作为`yield`表达式的结果,`throw()`方法用于在生成器中引发一个异常,`close()`方法用于关闭生成器。 PEP342进一步增强了生成器函数的功能,将`yield`从一个关键字(statement)变为表达式(expression),并引入了`send()`,`throw()`,`close()`等方法来操作生成器。这些增强使得生成器函数更加灵活和功能强大。 通过使用生成器函数,我们可以按需生成序列中的值,而不需要一次性生成所有的值,这样可以节省内存并提高效率。此外,生成器函数还可以用于实现协程和异步编程等高级应用。 参考文献: PEP 342 -- Coroutines via Enhanced Generators: https://www.python.org/dev/peps/pep-0342/ Real Python - Introduction to Python Generators: Using Advanced Generator Methods: https://realpython.com/introduction-to-python-generators/#using-advanced-generator-methods Real Python - Generators in Python: Creating and Iterating Simple Generators: https://realpython.com/introduction-to-python-generators/<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [python yield关键字全面解析](https://blog.csdn.net/jeffery0207/article/details/124856788)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值