Python 生成器

什么是生成器:

  • 生成器是 Python 中的一个对象(按照某种规律,来生成元素的对象),生成器不是列表,保存了产生元素的算法,同时会记录游标的位置(现在拿到第几个元素了),为了下次继续拿数据,而不是从头开始拿数据。可以通过一直调用 next() 方法获取值,这个对象不保存数据,每次调用会返回一个值,即做到了列表的好处,又不占用空间。
  • 在 Python 中,这种一边循环一边计算的机制,称为生成器:generator,生成器是在需要用到数据的时候再提供,相比列表生成器一次性生成多个数据,不占内存
  • 生成器是一个特殊的程序,可以被用作控制循环的迭代行为,Python 中生成器是迭代器的一种,使用 yield 返回值函数,每次调用 yield 会暂停,而可以使用 next() 函数和 send() 函数恢复生成器。

生成器的创建方式:

  • 生成器表达式
    • a = (expression for iterm in iterable)
  • 生成器函数
    • 在一个普通函数中使用 yield 关键字 
      • yield 类似于 return 函数,可以将 yield 后面的对象返回,并且记住这个返回的位置,下次通过 next 迭代时,代码从 yield 的下一条语句开始执行。
  • 生成器函数内部,不允许使用 return 语句返回任何值,因为生成器函数已经默认返回一个生成器了,但是你可以只写一个 return,后面不带任何值

生成器的取值方式:

  • 通过 next() 函数取值
  • 通过 send(value) 函数取值
    • 通过 next 和 send 函数取值时,当时取完了,会报 StopIteration 停止迭代错误
    • 第一次 send 前如果没有使用 next 函数进入生成器,则第一个 send 只能传入参数 None,send 类似于 next 可以进入生成器中去执行代码,但是 send 需要传入参数,且将传入的参数赋值给代码中的 yield 前的变量
  • 通过 for 循环取值
    • 因为生成器本身就是一个特殊的迭代器

 实例如下,定义生成器及通过 next 和 for 循环执行取值:

复制代码
# 第一种创建生成器的方式
b = (i for i in range(5))
print(b)    # <generator object <genexpr> at 0x0000000000F5B360>  generator 是一个生成器

# print(b.__next__()) # 通过私有方法 __next__() 进入生成器中取值
# print(next(b))  # 通过内置函数 next() 进入生成器中取值,依次取值,取完后再取就报迭代结束错误

for x in b: # 通过 for 循环取值,生成器本身是一个迭代器,是一个可迭代对象
    print(x)
复制代码
复制代码
# 第二种创建生成器的方式 通过yield创建
def func():
    print("hello1")
    yield 1     # yield 类似return,具有返回值作用
    print("hello2")
    yield 2

f = func()
print(next(f)) # 第一次next执行到yield1  结果:hello1和1
print(next(f)) # 第二次next从yield1开始执行,执行到yield2停止    结果:hello2和2

# 结果如下:
hello1
1
hello2
2
复制代码
复制代码
# 斐波那契数列 0 1 1 2 3 5 8
def fibo(max):
    n, before, after = 0, 0, 1
    while n < max:
        print(after)
        before, after = after, before+after
        n += 1

fibo(3)

# 通过生成器计算斐波那契数列
def fibo(max):
    n, before, after = 0, 0, 1
    while n < max:
        yield after
        before, after = after, before+after
        n += 1
f = fibo(3)
for i in f:
    print(i)

# 结果如下
1
1
2
复制代码

 实例如下,定义生成器及通过 send 执行取值:

复制代码
# send()函数
def func():
    print("hello1")
    count1 = yield 1
    print(count1)
    print("hello2")
    count2 = yield 2
    print(count2)
    yield 3

f = func()
# print(f.next())
#      ||   上下两行代码相等
print(f.send(None))  # 第一次send()前如果没有next(),只能传入一个None,send类似与next可以进入生成器中去执行代码,但是send需要传入参数,且传给代码中yeild前的变量count1
print("--------------")
print(f.send("world1"))
print("--------------")
print(f.send("world2"))

# 结果如下
hello1
1
--------------
world1
hello2
2
--------------
world2
3
复制代码

 

posted @   一个老宅男  阅读(340)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
历史上的今天:
2019-11-01 python(数据精度处理)
2019-11-01 App 自动化环境搭建(基于 Appium)
2019-11-01 python(类多态)
2019-11-01 python(类继承)
2019-11-01 Python 中的实例方法、类方法、静态方法的区别
2019-11-01 python(面向对象-类封装调用)
点击右上角即可分享
微信分享提示