Python迭代器(生成器)删除源码,仍然有效。发生了什么事?

时间:2018-02-01 02:05:47

标签: python generator

在使用生成器时,我需要澄清以下行为的内容。我担心我遗漏了一些基本的东西,所以欢迎任何建议。

(编辑)具体来说,我的问题涉及创建迭代器的迭代的del

我的最终用例是我正在迭代一个非常庞大的语料库进行文本处理。它不是那么大,以至于无法保存在内存中,但足够大,以至于无法在内存中训练后续模型。

所以,在我的调查中,我尝试了以下内容,我很困惑这是如何工作的。

>>> iterable = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
>>> iterable.__sizeof__()
    160
>>> iterator = (x+1 for x in iterable)
>>> iterator
<generator object <genexpr> at 0x1019f8570>
>>> iterator.__sizeof__()
64
>>> del iterable
>>> for i in iterator:
...     print(i)
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

一旦删除了iterable,迭代器引用的是什么?它是如何仍然能够拥有更小的mem足迹而且还能成功执行(我的印象是生成器只是指向现有数据,但如果它被删除,我必须耸耸肩?)

我错过了什么? (事情清楚。抱歉。我是自学成才)。提前致谢!

1 个答案:

答案 0 :(得分:9)

我将此作为评论,但需要格式化才能明确:

>>> x = [1, 2, 3]
>>> y = [x]
>>> del x
>>> y
[[1, 2, 3]]

从本质上讲,它与您的示例相同:删除名称x的绑定对y的值完全没有影响,因为y抓住了对象x 在绑定y时已绑定。

以同样的方式,绑定到iterator的生成器表达式捕获了当前iterable iterator当时绑定的绑定。

然而,在所有情况下,这并非完全直截了当。您可以read the PEP that introduced generator expressions了解详情。特别参见&#34;早期结合与晚期结合&#34;部分。

  

仅立即评估最外层的for-expression,其他表达式将延迟到生成器运行

你很幸运&#34;这里(但以一种非常常见的方式)因为iterable位于&#34;最外面的for-expression&#34;您的生成器表达式。对象iterable被绑定的原因是在您创建genexp时捕获的