python生成器

from icecream import ic
import time
import sys
import collections.abc
# time.clock()  # 获取cpu开始工作的时间。time.clock()在python3已经不推荐使用了,在python3.8中被废除了。
t1 = time.time()
ic([i for i in range(1, 18) if i % 2 == 0])  # 有判断条件,耗时长。列表是一次性全部生成数据
costTime = time.time()-t1
print('耗时:%g' % costTime)  # 耗时:0.906052。%g:指数(e)或浮点数(根据显示长度)
'''
在Python中,一边循环一边计算的机制,称为生成器(Generator)。生成器保存的是算法。
生成器是用来推算列表元素的,通过列表生成式,我们可以直接创建一个列表。
但是,受到内存限制,列表容量肯定是有限的。如果创建一个包含100万个元素的列表,会占用很大的存储空间。
而我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,我们可以在循环的过程中不断推算出后续的元素。
这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
所以生成器是为了生成列表时节省储存空间的产物,这样生成器会销毁也就不难理解了
'''
# 生成器是一种特殊的迭代器
t2 = time.time()
# 生成器的生成方式一:括号()。将列表生成式的[]改成()
g = (i for i in range(2, 28, 2))
print(g)  # <generator object <genexpr> at 0x0000000009E80190> 生成器对象
print(sys.getsizeof(g))  # 112  生成器内存开销112个字节
print(type(g))  # <class 'generator'> 类型为生成器
print(isinstance(g, collections.abc.Iterable))  # True  生成器是可迭代对象
print(g.send(None))  # 2   # 使用send()方法访问时,若访问生成器的第一个元素,需传入参数'None', 访问其余元素时,可任意传参。
print(next(g))  # 4 法一:用next方法访问生成器的下一个元素
print(g.__next__())  # 6 法二:用.__next__()方法访问生成器的下一个元素
print(next(g))  # 8
print(g.__next__())  # 10
print(g.send('abc'))  # 12 使用send()方法访问时,若访问生成器的第一个元素,需传入参数'None', 访问其余元素时,可任意传参。
print(g.send(None))  # 14  send()方法访问其余元素时,可任意传参。
for i in g:  # 用for循环遍历访问余下的内容
    print(i, end=' ')
print('\n')
ic(i for i in range(2, 18, 2))  # 生成器(记录算法),一边循环一边计算
ic([i for i in range(2, 18, 2)])  # 列表
ct2 = time.time()-t2
print('耗时:%g' % ct2)
print([a+b for a in '123' for b in 'xyz'])

# 生成器的生成方式二:函数中使用yield关键字。
'''一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,
直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,
但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。
看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。
yield 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,
比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰。'''


def func1():  # 带有 yield 的函数在 Python 中被称之为 generator(生成器)
    for i in range(5):
        yield i
# yield就是 return 返回一个值,并且记住返回的位置,下次迭代就从该位置开始。

f1 = func1()
print(type(f1))  # <class 'generator'>
print(next(f1))  # generator保存的是算法,每次调用next(),就计算出下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
print(f1.__next__())
print(next(f1))
print(f1.__next__())
print(f1.send('abc'))
print(next(f1))  # 超出范围,导致停止。


def func2():  # 带有 yield 的函数在 Python 中被称之为 generator(生成器)
    for i in range(5):
        pass


f2 = func2()  # Function 'func2' doesn't return anything
print(type(f2))  # <class 'NoneType'>

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值