什么是生成器:

  • 生成器是 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

 

原文地址:http://www.cnblogs.com/ZhengYing0813/p/16847219.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性