“双”迭代器和生成器函数

时间:2018-04-30 12:08:33

标签: python iterator generator

我希望使用类似迭代器的对象获取“下一个资源”,但是(而不是__next__()方法)有两个算法加载下一个资产(next1next2下面) ,可以实现为“准迭代器”,如:

class AssetLoader(object):
    def __init___(self):
        pass

    def next1(self):
        # ...

    def next2(self):
        # ...

要明确的是,下一个检索到的对象可能取决于调用next1next2的“历史记录”,例如:

next1(); next1(); next2(); next1(); next2()

我的问题:可以将(迭代器中的两种“下一步”)作为生成器函数实现吗?

我想这可以通过函数引用的全局变量来完成。但它可以不使用全局变量,但使用一些局部变量吗?

如果使用当前的Python很难或不可能,我们是否可以讨论如何向Python添加新的语义以使其成为可能?

2 个答案:

答案 0 :(得分:3)

这是一个使用send在两种不同迭代模式之间切换生成器的简单示例:它可以递增当前值或将其相乘。相同的原理可以应用于图形遍历任务。

send方法允许您将对象发送到生成器。令人讨厌的是,send的结果是您通过调用next获得的当前值;如果你能在不让发电机产生价值的情况下发送,那将是很好的,但这只是我们必须忍受的东西。

def add_or_mul(current, step, scale, mode='add'):
    ''' A generator that either adds step to the current value,
        or multiplies it by scale
    '''
    while True:
        newmode = yield current
        if newmode is not None:
            if newmode not in ('add', 'mul'):
                raise ValueError('Bad mode: ' + newmode)
            mode = newmode
        if mode == 'add':
            current += step
        else:
            current *= scale

# Test

    gen = add_or_mul(1, 1, 2)
    for i in range(5):
        print(next(gen))
    print(gen.send('mul'))
    for i in range(4):
        print(next(gen))
    print(gen.send('add'))
    for i in range(4):
        print(next(gen))       

<强>输出

    1
    2
    3
    4
    5
    10
    20
    40
    80
    160
    161
    162
    163
    164
    165

如果您在将此技术应用于图形遍历任务时遇到问题,请提出一个新问题(可能链接到此问题),其中包含一些相关的图形代码,以便回答者不必从头开始编写这些内容测试并演示他们的代码。

答案 1 :(得分:1)

你可以试试这个:

class AssetLoader(object):
    def __init___(self):
        self.current_next = self.next1

    def next1(self):
        if condition:
            self.current_next = self.next2
        elif conition:
            return x
        else:
            raise StopIteration

    def next2(self):
        if condition:
            self.current_next = self.next1
        elif conition:
            return y
        else:
            raise StopIteration

    def __next__(self):
        return self.current_next()

    def __iter__(self):
        return self