在这两个例子中,生成器在内存方面的优势是什么?



生成器的优点之一是使用更少的内存和消耗更少的资源。也就是说,我们不会一次生成所有数据,也不会为所有数据分配内存,而且每次只生成一个值。存储变量的状态、状态和值,实际上可以通过调用继续来停止和恢复代码。

我写了两个代码,我正在比较它们,我看到生成器可以正常编写,现在我没有看到生成器的任何点。谁能告诉我这个生成器的优点是什么,当它被正常编写?它们的每次迭代都会生成一个值。

第一个代码:

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))

我知道gid是恒定的,而func(i)id是变化的。

这就是主发电机优势的意思吗?

具体来说,你在问题中提到的上述代码,你所展示的两种方法在内存方面没有区别,但第一种方法更可取,因为你需要的一切都在同一个生成器函数中,而在第二种情况下,循环和函数位于两个不同的地方,每次你需要使用第二个函数时,您需要在外部使用循环,这不必要地增加了冗余。

实际上你写的两个函数,一个是生成器函数,一个是普通函数,它们是不等价的。在生成器中,您将返回所有值,即循环在生成器函数中:

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,但在第二种情况下,在你真正处理它之前,你最终将整个结果存储在内存中。

主要优点是当您拥有大型数据集时。这基本上是lazy loading的思想,这意味着除非需要,否则不会调用数据。这节省了你的资源,因为通常在一个列表中,整个东西是一次加载的,如果数据足够大,可能会占用很多主内存。

第一个代码的优点是相对于您没有显示的东西。这意味着一次生成和消费一个值比首先生成所有值,将它们收集到列表中,然后从列表中消费它们占用的内存要少。

用来比较第一个代码的第二个代码应该是:

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使用更多的内存,而gen使用相同数量的内存,无论n有多大。

最新更新