参考资料:https://www.bilibili.com/video/BV1aK4y1k7jZ?from=search&seid=12219686198146507215
一、Generator基本用法
1.什么是generator
Generator是一个生成器,可以生成一个个东西,可以通过next()
函数依次生成, 它是一个iterable。
nums = [1,2,3,4,5]
square_nums = (n*n for n in nums)
print(square_nums)
# 结果:<generator object <genexpr> at 0x01AC10B0>
从上面的结果中我们可以看到,print
出来是一个generator对象,而不是列表,但它其中有我们需要的列表。
for n in square_nums:
print(n)
# 等于
next(square_nums)
next(square_nums)
next(square_nums)
next(square_nums)
next(square_nums)
for循环这里调用iterable的next(square_nums)
。
2. 为什么要用Generator
在Generator中,所有可以遍历的对象没有一次全部生成出来,而是在需要的时候产生。(不会一次性生成所有,而占用大量内存)
如下,生成列表,所需要的内存和时间远远大于生成generator所需要的内粗和时间:
yi = 100000000
nums = list(range(10000000))
#直接生成列表所需的内存和时间
start_list = time.time()
memo_list = mem.memory_usage()[0]
square_nums = [n*n*yi for n in nums]
end_memo_list = mem.memory_usage()[0]
end_list = time.time()
print(f'直接生成列表所用内存:{end_memo_list - memo_list},所用时间{end_list - start_list}')
结果:直接生成列表所用内存:269.390625,所用时间2.9482293128967285
yi = 100000000
nums = list(range(10000000))
# 生成generator所需要的内存和时间
start_gene = time.time()
memo_gene = mem.memory_usage()[0]
square_nums = (n*n*yi for n in nums)
end_memo_gene = mem.memory_usage()[0]
end_gene = time.time()
print(f'使用generator所需内存:{end_memo_gene - memo_gene},所用时间{end_gene - start_gene}')
结果:使用generator所需内存:0.00390625,所用时间0.2151331901550293
二、Yield
当我们不用生成器时,calc_nums
方法会帮我们计算出来所有的值并放入列表中,
value = 2
nums = list(range(100))
def calc_nums(nums):
new_list = []
for n in nums:
if n%3 == 0:
new_nums.append(3 * value)
elif n%5 == 0:
new_nums.append(5 * value)
else:
new_nums.append(n * value)
return new_list
当我们想定义一个generator对象的函数,我们需要用yield
返回结果,这样会依次返回每一个。生成器在碰到依次yield的时候,会返回一个关系,这个函数没有真正的结束,当我们调用next(),会继续进行其中的下一个。
def gen_nums(nums):
for n in nums:
if n%3 == 0:
yield 3*value
elif n%5 == 0:
yield 5*value
else:
yield n*value