【问题标题】:Example python implementation of generator/yield生成器/产量的示例 python 实现
【发布时间】:2020-06-10 16:58:51
【问题描述】:

让我们用下面的python代码来生成一个无限计数器:

def infinite_sequence():
    num = 0
    while True:
        yield num
        num += 1

然后我可以将其称为:

for i in infinite_sequence():
    print (i)

每当我想退出它时,请执行KeyboardInterruptyield/generator 的东西是用 C/Cpython 实现的。在 python 中实现类似的“生成器功能”的例子是什么?也就是说,如果我可以调用一个函数/方法来代替 yield num 行,并获得相同的功能,那么 python 中的示例实现是什么?

【问题讨论】:

    标签: python python-3.x generator yield python-internals


    【解决方案1】:

    您必须自己实现迭代器协议。

    class InfiniteSequence:
        def __init__(self):
            self.x = 0
    
        def __iter__(self):
            return self
    
        def __next__(self):
            x = self.x
            self.x = x + 1
            return x
    
    
    for i in InfiniteSequence():
        print(i)
    

    __iter__ 方法必须返回实现__next__ 的东西。 __next__ 方法必须返回序列中的下一个值。实例属性在对__next__ 的调用之间维护状态。

    同一个类不必同时实现这两种方法。您可能需要一个单独的迭代器类,以便可以在可迭代序列上拥有多个独立的迭代器。

    class InfiniteSequence:
        def __init__(self, start):
            self.start = start
    
        def __iter__(self):
            return InfSeqIterator(self.start)
    
    
    class InfSeqIterator:
        def __init__(self, x):
            self.x = x
    
        def __iter__(self):
            return self
    
        def __next__(self):
            x = self.x
            self.x += 1
            return x
    
    
    nats = InfiniteSequence()
    
    i1 = iter(nats)
    i2 = iter(nats)
    
    assert next(i1) == 0
    assert next(i2) == 0  # not 1
    

    generator 只是实现此协议的类的一个示例;您可以使用生成器表达式 ((x for x in [1,2,3])) 或生成器函数(即使用 yield 的函数)创建 generator 的实例。

    【讨论】:

    • python/cpython 如何从yield 语句的上下文中推断出__next__ 方法(或其等效方法)?
    • 这确实是一个检查您感兴趣的任何实现的源代码的问题;这不是 Python 语言定义的。
    • 为什么在递增self.x时需要绕道?
    • 因为要返回self.x的当前值,而不是增量值。您可以通过将self.x 初始化为比起始值小一来避免这种情况;然后你可以增加它并返回它。我只是没有。
    • @chepner 你能链接到迭代器协议的python部分吗?这是 C 版本:docs.python.org/3/c-api/iter.html。作为旁注,我希望 python 的文档在搜索中得到更好的表现(在谷歌和 python 搜索本身都很差)。
    猜你喜欢
    • 2020-01-18
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多