【问题标题】:Detect whether generator's __iter__ is called with list()检测生成器的 __iter__ 是否被 list() 调用
【发布时间】:2012-02-22 18:34:02
【问题描述】:

有没有办法检测生成器的__iter__ 是否被list() 调用?据我了解, list(obj) 将调用__iter__;但是,对于无限生成器,我希望它返回错误。

例如,我有以下生成器:

def gen():
    while 1:
        yield 1

由于调用 list(gen) 会导致无限循环,我想让它返回一个错误。有没有办法做到这一点?

【问题讨论】:

  • __iter__ 没有责任确保这一点,我也不认为这是list() 的责任。这是程序员的责任!
  • 你想用这个保护谁?如果您适当地命名无限生成器,那么编写对生成器的调用的人应该清楚发生了什么;例如如果你写list( allPrimeNumbers() ),你应该得到你所得到的。

标签: python generator


【解决方案1】:

没有明智的方法可以做到这一点。您也许可以劫持堆栈跟踪,但它会很丑陋且容易出错。

(显然,您想要做的不是预期可迭代对象在 Python 中的行为方式,这是不这样做的另一个很好的理由。)

此外,它不会永远循环,但会继续尝试为列表分配内存。一旦失败,MemoryError 将被抛出,解释器可能会或可能不会恢复。

【讨论】:

  • 谢谢。我可能会使用单独的 next__iter__ 属性将自定义类型组合在一起。
  • 你不是基本扩展了我说的吗?
【解决方案2】:

如果没有可怕的黑魔法,我不会在这里介绍。只需在文档字符串中写下“这不是详尽无遗的”。并尽量记住不要调用列表就可以了。

【讨论】:

    【解决方案3】:

    虽然这不是我要求的,但这里有一个基本相同的解决方案:

    class test:
        def __init__(self):
            self.generate = self.gen()
            self.next = self.generate.next
        def gen(self):
            for a in range(10):
                yield a
        def __iter__(self):
            raise ValueError
    
    >>> a = 测试() >>> a.next() 0 >>> 列表(一) 值错误:

    【讨论】:

      猜你喜欢
      • 2014-04-17
      • 2020-11-22
      • 1970-01-01
      • 1970-01-01
      • 2015-01-19
      • 2011-10-13
      • 2019-05-23
      • 2014-05-10
      • 1970-01-01
      相关资源
      最近更新 更多