生成器的优势之一是它使用更少的内存和消耗更少的资源。也就是说,我们不会一次生成所有数据,也不会为所有数据分配内存,并且每次只生成一个值。存储变量的状态、状态和值,实际上可以通过调用代码继续来停止和恢复代码。
我写了两个代码,我正在比较它们,我看到生成器可以正常编写,现在我看不到生成器的任何点。谁能告诉我这个生成器与正常编写时相比有什么优势?它们的每次迭代都会生成一个值。
第一个代码:
def gen(n):
for i in range(n):
i = i ** 2
i += 1
yield i
g = gen(3)
for i in g:
print(i)第二个问题:
def func(i):
i = i ** 2
i += 1
return i
for i in range(3):
print(func(i))我知道g的id是恒定的,而func(i)的id是在变化的。
这就是主生成器优势的含义吗?
发布于 2021-08-08 09:25:41
具体地说,您在问题中提到的上述代码在内存方面没有区别,但第一种方法更可取,因为您需要的所有东西都在同一个生成器函数中,而在第二种情况下,循环和函数位于两个不同的位置,每次需要使用第二个函数时,您都需要在外部使用循环,这会不必要地增加冗余。
实际上,你写的两个函数,生成器函数和普通函数,它们不是等价的。在生成器中,您将返回所有值,即循环位于生成器函数内部:
def gen(n):
for i in range(n):
i = i ** 2
i += 1
yield i但是,在第二种情况下,您只返回一个值,并且循环位于函数外部:
def func(i):
i = i ** 2
i += 1
return i为了使第二个函数等同于第一个函数,您需要在函数中包含循环:
def func(n):
for i in range(n):
i = i ** 2
i += 1
return i现在,当然,如果控制进入循环内部,上面的函数总是为i=0返回一个值,所以要解决这个问题,你需要返回一个完整的序列,这要求你有一个列表或类似的数据结构,允许你存储多个值:
def func(n):
result = []
for i in range(n):
i = i ** 2
i += 1
result.append(i)
return result
for v in func(3):
print(v)
1
2
5现在,您可以清楚地区分这两种情况,在第一种情况下,每个值都会按顺序进行计算,然后再进行处理,即printed,但在第二种情况下,在实际处理之前,您最终会将整个结果保存在内存中。
发布于 2021-08-08 09:19:50
主要的优点是当你有一个大型数据集的时候。它基本上是lazy loading的思想,这意味着除非需要,否则不会调用数据。这节省了您的资源,因为通常在列表中,整个内容是一次性加载的,如果数据足够大,这可能会占用大量的主内存。
发布于 2021-08-08 09:25:11
第一个代码的优点是关于您没有显示的东西。一次生成和使用一个值比首先生成所有值,然后将它们收集到一个列表中,然后从列表中使用它们所需的内存更少。
要与第一个代码进行比较的第二个代码应该是:
def gen2(n):
result = []
for i in range(n):
i = i ** 2
i += 1
result.append(i)
return result
g = gen2(3)
for i in g:
print(i)请注意,如何使用gen2的结果与第一个示例中的gen的结果完全相同,但是如果n越来越大,gen2将使用更多内存,而无论n有多大,gen都将使用相同数量的内存。
https://stackoverflow.com/questions/68699333
复制相似问题