在玩发电机的过程中,我找到了有趣的东西。当我用yield
关键字定义一个函数时,从它接收了一个生成器,我还删除了带有序列的变量,该变量被输入到函数中。并且* POOF!* - 发电机变空。这是我的步骤:
>>> def foo(list_):
... for i in list_:
... yield i*2
...
>>> val = [1, 2, 3, 4]
>>> gen = foo(val)
>>> print(tuple(gen))
(2, 4, 6, 8)
>>> del val
>>> print(tuple(gen))
()
>>>
它不应该是不可变的吗?或者,如果它实际上作为对象将其变量的所有值提供给它的函数,给出输出,为什么它没有因为没有链接序列而抛出异常?实际上,这个例子可以解释为我迭代一个空序列,这导致块for _ in []:
永远不会启动。但是,我无法解释为什么这个不会抛出异常:
>>> def foo(list_):
... for i in list_:
... yield i*2
...
>>> val = [1, 2, 3, 4]
>>> gen = foo(val)
>>> print(tuple(gen))
(2, 4, 6, 8)
>>> del foo
>>> print(tuple(gen))
()
>>>
此处的生成器是否与dict.get()
函数类似?我不明白这一点。
答案 0 :(得分:4)
这与被删除的对象无关。相反,你已经耗尽了发电机;生成器只能迭代一次。如果需要再次迭代,请从生成器函数创建新的生成器。您在不删除引用的情况下看到相同的行为:
del foo
请注意,del val
或gen = foo(val); del foo, val
仅删除对象的引用。如果存在对其的其他引用,则不会完全删除该函数或列表对象,例如从该函数创建的现有生成器。因此gen
不会破坏foo
对象,它仍然可以在没有val
或gen
引用的情况下生成值,因为>>> gen = foo(val)
>>> del foo, val
>>> list(gen) # gen still references the list and code objects
[2, 4, 6, 8]
本身仍然引用了什么它需要完成:
If(record does not exists in target table)
If(dbcal is not set)
Insert
Else
Reject
Else if(record exists in target table)
If(dbcal is not set)
Update
Else
Delete