【问题标题】:How to avoid the extra iterations when using Python coroutines?使用 Python 协程时如何避免额外的迭代?
【发布时间】:2021-09-01 09:52:03
【问题描述】:

这是 Python 3.9 中的协程

def coroutine(func):
    def start(*args, **kwargs):
        cr = func(*args, **kwargs)
        next(cr)
        return cr
    return start


@coroutine
def grep(pattern):
    while True:
        line = yield "I have to yield something here?"
        if pattern in line:
            # do something fancy to the line
            yield line
        else:
            raise ValueError("err")

由于line = yield 正在接收和发送数据,我需要进行额外的next 调用才能使其工作:

gg = grep("thing")

item = gg.send("That thing!")
print(item)
next(gg)

item = gg.send("That thing also!")
print(item)
next(gg)

item = gg.send("And what about here this thing.")
print(item)
next(gg)

item = gg.send("Not this.")
print(item)
next(gg)

哪个打印:

That thing!
That thing also!
And what about here this thing.
Traceback (most recent call last):
  File "/home/erasmose/Workspace/clustr/cmapper/temp.py", line 33, in <module>
    item = gg.send("Not this.")
  File "/home/erasmose/Workspace/clustr/cmapper/temp.py", line 16, in grep
    raise ValueError("err")
ValueError: err

如果我删除“下一个”调用:

gg = grep("thing")

item = gg.send("That thing!")
print(item)

item = gg.send("That thing also!")
print(item)

item = gg.send("And what about here this thing.")
print(item)

item = gg.send("Not this.")
print(item)

输出是:

That thing!
I have to yield something here?
And what about here this thing.
I have to yield something here?

有什么方法可以避免那些额外的“下一个”调用?

【问题讨论】:

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


    【解决方案1】:

    您需要合并两个yield 语句,以便协程在同一个yield 中发送和接收

    不过,您仍然需要额外的收益来启动该过程。

    类似这样的:

    
    @coroutine
    def grep(pattern):
        line = yield "I have to yield something here?"  # receive the first one
        while True:
            if pattern in line:
                line = yield line  # send and receive in one yield statement
            else:
                raise ValueError("err")
    

    【讨论】:

    • 感谢@sabik 的回答。在产生它之前,我需要对line 进行一些处理。这是一个简化的代码。如何获取line,在同一行代码中处理并生成它?
    • line = yield line 语句产生上一行,然后接收下一行;您可以在该语句之前进行所有处理(在循环内)
    • 如果您愿意,可以改用next_line = yield line
    猜你喜欢
    • 2016-07-15
    • 2012-01-26
    • 1970-01-01
    • 2017-02-21
    • 2013-07-09
    • 2021-09-04
    • 2014-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多