生成器
生成器其实就是一种特殊的迭代器, 用过yield语法实现
代码1
import math
# 2是最小的质数
number = 2
def is_prime_number(number):
"""判断传入数字是否是质数"""
end = int(math.sqrt(number)) + 1
for i in range(2, end):
if math.remainder(number, i) == 0:
return False
return True
def generate_prime_number():
"""质数生成器"""
global number
while True:
tmp = number
number += 1
if is_prime_number(tmp):
yield tmp
def main():
"""输出100以内的所有质数"""
for _ in range(24):
print(next(generate_prime_number()), end=', ')
print(next(generate_prime_number()))
if __name__ == '__main__':
main()
输出:
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
解释:
使用了yield关键字的函数不再是普通函数,而是生成器(generator), 生成器是一类特殊的迭代器
yield关键字有两点作用:
- 保存当前运行状态, 即遇到 yield 后暂停执行,即将生成器挂起
- 将 yield 后面的值返回
- 使用 next() 函数唤醒生成器从而继续执行
PS: 把列表推到式外面的[]换成()就是一个生成器, 然后可以使用next()方法输出其元素
代码2
def fibonacci_sequence(n):
"""斐波那契数列"""
current = 0
num1, num2 = 1, 1
while current < n:
num = num1
num1, num2 = num2, num1 + num2
current += 1
yield num
# 触发StopIteration异常时可返回的值
return '没有了'
def main():
fs = fibonacci_sequence(6)
while True:
try:
print(next(fs))
except StopIteration as e:
print(e.value)
break
if __name__ == '__main__':
main()
输出:
1
1
2
3
5
8
没有了
解释:
当引发StopIteration异常时, 生成器函数fibonacci_sequence中return后的值可以被输出
main函数中必须先定义变量 fs = fibonacci_sequence(6), 再使用 next(fs)
否则会无限循环输出 1
因为每次都调用函数,都是一个新的实例,每次都都从第一个数据开始取
对比代码1, 并没有设置变量, 之所以直接调用的结果依旧正确, 是因为设置了一个全局变量, 每次调用的初始条件都不一样
生成器中还有一个send方法, 详情见: https://blog.csdn.net/qq_42103091/article/details/124995095