python-生成器(通俗详解)

生成器:含有yield的函数。(无需借助类就能实现)

功能:函数执行过程中可中断、可重开、可暂停、可续传

为什么要用生成器? 解决内存占用问题,看最后一段代码。

原理:是基于迭代器来实现(既然生成器是一个迭代器,它可以被用在for 循环中),内部会自动创建__iter__()和__next__()方法。

运行规则:

遇到yield,程序暂停,并返回值,下次还从该位置运行

对比return则是程序停止,并返回值

基本语法:

def myGen():
    print('生成器执行')
    yield 1
    yield 2

使用方法1:

>>> my = myGen()
>>> next(my)
    生成器执行
    1

>>> next(my)
    2

>>> next(my)
    错误:StopIteration

使用方法2:

    通过迭代器可知,for循环可以捕获StopIteration,并结束
>>> for i in myGen():
        print(i)
    生成器执行
    1
    2

生成器推导式:

e = (i for i in range(5))  # e 也是一个生成器
next(e)
0
next(e)
1
for each in e:
    print(each)
2
3
4

生成器的另一种结构:

def foo():
    while True:
        res = yield 4
        print("res:",res)
        
g = foo()	# 得到了生成器
print(next(g))	# 开始运行生成器g,第一次返回值为4,此时生成器停止
print(next(g))	# 第二次运行:由于4被返回。所以并没有赋值给res,res为None,返回4

# 运行结果
4
res: None
4

代码解析:

g = foo()

g得到了生成器

 print(next(g))

开始运行生成器g,第一次返回值为4,此时生成器停止

 print(next(g))

第二次运行:由于4被返回。所以并没有赋值给res,res为None,返回4

注意:和一般的赋值语句不同,res的值并不是通过yield后面的值赋值的吼

(因为后面的值被返回了,怎么赋?怎么赋?没法赋!没法赋!)

那么res的值时谁赋予的呢?
我们再来看一个小栗子:

def foo():
    while True:
        res = yield 4
        print("res:",res)
        
g = foo()	# 得到了生成器
print(next(g))	# 开始运行生成器g,第一次返回值为4,此时生成器停止

# 以上:和之前一样
print(g.send(7))	# 生成器g 的send()方法,从外部把7送到了生成器内部,赋值给了res

# 运行结果
4
res: 7
4

代码解析:

print(g.send(7))	:

生成器g的send()方法: 从外部把7送到了生成器内部,赋值给了res

由此可见:res的值是通过send()方法,从外部传递的

调用send()与使用next()有点像,都会使生成器进行下一次运行。不同的是send()可以往里传入一个值给res

小栗子:

10 以内的素数之和是:2 + 3 + 5 + 7 = 17
那么请编写程序,计算 2000000 以内的素数之和

如果先把所有的素数找到存在列表里,再累加求和,则占用太大内存可能溢出
用生成器:一次找到一个素数,找一个加一个,不占用内存

import math

# 判断是否为素数
def is_prime(number):       
    if number > 1:
        if number == 2:
            return True
        if number % 2 == 0:
            return False
        for current in range(3, int(math.sqrt(number) + 1), 2):
            if number % current == 0:
                return False
        return True
    return False

# 生成器函数
def get_primes(number):
    while number:
        if is_prime(number):
            yield number
        number -= 1


a = 0   
for each in get_primes(2000000):
    a += each   # 每次产生一个值累加

print(a)    # 142913828922

如果你感觉对你有帮助,你的赞赏是对我最大的支持!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值