简体   繁体   English

“ Double”迭代器和生成器功能

[英]“Double” iterator and a generator function

I want to get "next asset" with an iterator-like object, but (instead of __next__() method) there are two algorithms loading next asset ( next1 and next2 below), which can be implemented as a "quasi-iterator" like: 我想使用类似迭代器的对象来获取“下一个资产”,但是(而不是__next__()方法)有两种算法加载下一个资产(下面的next1next2 ),它们可以像“准迭代器”一样实现:

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

    def next1(self):
        # ...

    def next2(self):
        # ...

To be clear, what is the next retrieved object may depends on the "history" of calling next1 and next2 , like: 需要明确的是,下一个检索到的对象是什么,可能取决于调用next1next2的“历史”,例如:

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

My question: May this (two kinds of "next" step in an iterator) be implemented as a generator function? 我的问题:是否可以将这个(迭代器中的两种“下一步”步骤)实现为生成器函数?

I guess this can be done with a global variable to which the function refers. 我猜这可以通过函数引用的全局变量来完成。 But can it be done without using global variables, but with some local variable? 但是,可以不使用全局变量而使用局部变量来完成此操作吗?

If it is hard or impossible with current Python, can we discuss how to add new semantics to Python to make it possible? 如果使用当前的Python很难或不可能,我们是否可以讨论如何向Python添加新的语义以使其成为可能?

Here's a simple example of using send to switch a generator between two different iteration modes: it either increments its current value or multiplies it. 这是一个使用send在两个不同的迭代模式之间切换生成器的简单示例:它要么增加其当前值,要么将其乘以它。 The same principle can be applied to your graph traversal task. 可以将相同的原理应用于图遍历任务。

The send method allows you to send an object into the generator. send方法允许您将对象发送到生成器中。 Annoyingly, the result of send is the current value that you would have obtained by calling next ; 令人讨厌的是, send的结果是您通过调用next获得的当前值; it would be nice if you could send without having the generator yield a value, but that's just something we have to live with. 如果您可以在不让生成器产生值的情况下进行发送,那将是很好的选择,但这只是我们必须忍受的。

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))       

output 输出

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

If you have trouble applying this technique to your graph traversal task please ask a fresh question (possibly linking to this one) that includes some relevant graph code, so that answerers don't have to write that stuff from scratch in order to test and demonstrate their code. 如果您在将此技术应用于图形遍历任务时遇到问题,请提出一个新问题(可能链接至此问题),该问题包括一些相关的图形代码,以便回答者不必从头开始编写即可测试和演示他们的代码。

You can try this: 您可以尝试以下方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM