有没有办法检查发电机是否在全球任何地方使用?这样,如果没有人使用,活跃的发电机就会退出

Is there a way to check if a generator is in use anywhere globally? Such that an active generator will bail if no one is using it

有没有办法检查全球任何地方是否正在使用发电机?这样一台活跃的发电机将保释没有人使用它。

这主要是学术性的,但我可以想到很多情况下最好检测到这一点。所以你明白了,这是一个例子:

def accord():
  _accord = None
  _inuse = lambda: someutilmodule.scopes_using(_accord) > 1
  def gen():
    uid = 0
    while _inuse():
      uid += 1
      yield uid
    else:
      print("I'm done, although you obviously forgot about me.")
  _accord = gen()
  return _accord

a = accord()
a.__next__()
a.__next__()
a.__next__()
a = None

"""
<<< 1
<<< 2
<<< 3
<<< I'm done, although you obviously forgot about me.
"""

如果 someutilmodule.scopes_using 报告变量的使用次数,我希望看到三重引号的文本。使用我的意思是存在多少副本或引用。

请注意,生成器有一个无限循环,这通常是不好的做法,但在唯一 ID 生成器和其他未广泛或复杂使用的情况下,它通常很有用,不会产生巨大的开销。显然,另一种方法是简单地公开一个函数或方法,该函数或方法将在循环使用的条件下看到标志。但同样,知道如何以各种方式做事是件好事。

在这种情况下,当你这样做时

a = accord()

幕后的引用计数器跟踪变量引用该生成器对象的事实。这会将它保存在内存中,因为将来可能会需要它。

一旦你这样做了:

a = None

生成器的引用丢失,与之关联的引用计数器减少。一旦它达到 0(它会,因为你只有一个对它的引用),系统知道没有任何东西可以再次引用该对象,这将释放与该对象关联的数据以供垃圾收集。

这一切都是在幕后处理的。不用你插手

了解正在发生的事情是好是坏的最好方法是检查相关的 source code for CPython。最终,当引用丢失时调用 _Py_DECREF 。在解释了一些复杂的逻辑之后,您可以进一步看到,一旦引用为 0,就会在 PyObject *op 上调用 _Py_Dealloc(op);。我这辈子都找不到对 free 的实际调用,尽管我确定最终是 _Py_Dealloc 的结果。它似乎在 Py_TRASHCAN_END 宏中的某个地方,但是上帝啊。这是我去过的最长的兔子洞之一,我没有任何东西可以展示它。