是否能够使用生成器函数而不使用yield? (Python3.x)

时间:2014-11-07 11:31:08

标签: python generator

在某些情况下,使用带yield的生成器可以方便地将数据传回给调用者一段时间。有没有办法做类似yield的事情,而不必将函数变成生成器?

原因是,在某些情况下,当这些嵌套函数可能具有有用的返回值时,我最终必须将所有被调用者都放入生成器中。

# currently this works fine, but requires a return arg

def nested(return_store):
    return_store[0] = some_test()
    yield from some_generator()

def do_stuff(return_store):

    yield some_data

    for more_data in data:
        yield more_data

    # Annoying workaround!
    return_store = [None]
    yield from nested(return_store)
    if return_store[0]:
        pass  # do anything


def main():
    return Reply(do_stuff())

相反,我想传递一个对象作为参数,我可以传递参数(而不是使用yield)

# is something like this possible?
def nested(iter_obj):
    iter_obj.yield_replacement(some_generator())
    return some_test()

def do_stuff(iter_obj):

    iter_obj.yield_replacement(some_data)

    for more_data in data:
        iter_obj.yield_replacement(more_data)

    # No annoying workaround
    if nested(iter_obj):
        pass  # do anything

def main():
    iter_obj = yield_replacement_object(consumer=print)
    # sets up the generator (Reply should consume iter_obj)
    do_stuff(iter_obj)
    return Reply(iter_obj)

1 个答案:

答案 0 :(得分:2)

生成器只是迭代器的一种形式。任何实现iterator protocol的东西都可以。

这意味着您可以使用具有更多属性的对象替换嵌套函数:

class Nested():
    def __iter__:
        self.some_flag = some_test()
        yield data

我将__iter__方法实现为生成器函数。

然后随意使用生成器中的对象:

n = Nested()
yield from n
if n.some_flag:
    # ...

另一种方法是抛出异常;如果您正在尝试传递一些带外状态更改,请抛出异常并在父生成器中捕获它。