杭州外贸网站建设公司价格,温州网络有限公司,网上销售有哪些方法,个人网页设计的意义文章目录 [toc]什么是生成器生成器示例生成器工作流程生成器表达式send()方法和close方法send()方法close()方法 什么是生成器
在Python中#xff0c;使用生成器可以很方便地支持迭代器协议生成器通过生成器函数产生#xff0c;通过def定义#xff0c;但不是通过return返回… 文章目录 [toc]什么是生成器生成器示例生成器工作流程生成器表达式send()方法和close方法send()方法close()方法
什么是生成器
在Python中使用生成器可以很方便地支持迭代器协议生成器通过生成器函数产生通过def定义但不是通过return返回而是通过yield一次返回一个结果在每个结果之间挂起和继续它们的状态来实现迭代器协议yield本质上是一个语法糖内部是一个状态机维护着挂起和继续的状态从而支持迭代器协议 生成器示例
def my_range(n):i 0while i n:yield ii 1my_range my_range(3)print(my_range)print(next(my_range))
print(next(my_range))
print(next(my_range))generator object my_range at 0x0000019CE75804A0
0
1
2在这个例子中定义了一个生成器函数my_range()调用生成器函数会返回一个生成器对象本质上是返回生成器对象的迭代器通常直接称为生成器既然生成器本质上是一个迭代器那么其内部需要实现__iter__()方法和__next__()方法dir()函数可以获取一个对象的所有属性和方法可以使用dir()函数查看生成器对象的属性和方法
def my_range(n):i 0while i n:yield ii 1my_range my_range(3)print(dir(my_range))print(__iter__ in dir(my_range))
print(__next__ in dir(my_range))[__class__, __del__, __delattr__, __dir__, __doc__, __eq__, __format__, __ge__, __getattribute__, __gt__, __hash__, __init__, __init_subclass__, __iter__, __le__, __lt__, __name__, __ne__, __new__, __next__, __qualname__, __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__, __str__, __subclasshook__, close, gi_code, gi_frame, gi_running, gi_yieldfrom, send, throw]
True
True生成器工作流程
在上面的例子中加入一些打印信息进一步看看生成器的工作流程
def my_range(n):print(开始迭代...)i 0while i n:print(迭代中...)yield iprint(- * 10)i 1print(迭代结束)gen_obj my_range(3)print(next(gen_obj))
print(next(gen_obj))
print(next(gen_obj))开始迭代...
迭代中...
0
----------
迭代结束
迭代中...
1
----------
迭代结束
迭代中...
2通过结果可以看到 当调用生成器函数的时候函数只是返回了一个生成器对象并没有运行当第一次调用next()方法的时候生成器函数才开始运行运行到yield语句处停止并将i作为返回值返回执行过程为图中的①当继续调用next()方法的时候生成器函数从上一次停止的地方也就是yield语句处继续运行直到再次运行到yield语句处停止 并将i作为返回值返回执行过程为图中的②③如果下一次迭代不能运行到yield语句就抛出StopIteration异常生成器在当前yield语句处停止不再执行②③过程 生成器表达式
在介绍生成器表达式之前先看看我们已经比较熟悉的列表解析
nums [i for i in range(10) if i % 2]print(nums)[1, 3, 5, 7, 9]上述列表解析返回一个包含 1 1 1到 10 10 10之间所有奇数的列表当序列很长而每次只需要获取一个元素时应当考虑生成器而不是列表解析生成器表达式的语法和列表解析一样只不过生成器表达式是被()括起来的
gen_obj (i for i in range(10) if i % 2)print(gen_obj)generator object genexpr at 0x000001D6DC1E04A0生成器表达式并不是返回一个列表而是返回一个生成器使用生成器时每迭代一次会产生yield出一个值来实现了惰性加载懒加载只有在被迭代时才被赋值并覆盖上一个值所以在序列较长的情况下使用生成器会优化内存 send()方法和close方法
生成器中有两个重要的方法send()方法和close方法
send()方法
在Python 2.5中yield语句变成了yield表达式也就是说yield可以有一个值而这个值就是send()方法的参数通过调用send()方法将值传递给yield而send()的返回值为yield返回的值所以send(None)和next()是等效的注意调用send()传入非None值前生成器必须处于挂起状态否则将抛出异常也就是说第一次运行生成器时只能使用next()或send(None)因为没有yield来接收这个值
def my_range(n):i 0while i n:var yield iprint(fvar 的值为 {var})i 1my_range my_range(3)print(my_range.send(None))
print(my_range.send(hello))
print(my_range.send(world))0
var 的值为 hello
1
var 的值为 world
2close()方法
close()方法用于关闭生成器对关闭后的生成器再次调用next()或send()将抛出StopIteration异常
def my_range(n):i 0while i n:var yield iprint(fvar 的值为 {var})i 1my_range my_range(3)print(my_range.send(None))
print(my_range.send(hello))my_range.close()print(my_range.send(world))0
var 的值为 hello
1
Traceback (most recent call last):File C:/Users/FOLLOW_MY_HEART/Desktop/Python基础/【Python基础】迭代器/test.py, line 18, in moduleprint(my_range.send(world))
StopIteration