在 Python 中重构协程
Refactor a coroutine in Python
我想重构一个协同程序,将它的一些代码移到另一个function/coroutine。但是我需要在包含协程中检索它的最后一个提要,但我不知道如何正确地做到这一点。
这是一个更简单的协程示例。
def coroutine():
"""Yield a string containing the number sent. If 5 is sent, block for 5 turns."""
feed = yield 0
while True:
if feed == 5:
for i in range(5, 0, -1):
feed = yield f"Blocked for {i} turns"
feed = yield f"Received {feed}"
if __name__ == "__main__":
my_coroutine = coroutine()
next(my_coroutine) # Init the coroutine
# Print the coroutine results for inputs from 0 to 14
for j in range(15):
print(f"{j} -> {my_coroutine.send(j)}")
我期望(并得到)的结果是
0 -> Received 0
1 -> Received 1
2 -> Received 2
3 -> Received 3
4 -> Received 4
5 -> Blocked for 5 turns
6 -> Blocked for 4 turns
7 -> Blocked for 3 turns
8 -> Blocked for 2 turns
9 -> Blocked for 1 turns
10 -> Received 10
11 -> Received 11
12 -> Received 12
13 -> Received 13
14 -> Received 14
现在,我想通过将可重用部分移动到协程来改进我的代码 wait_for_five_turns
:
def wait_for_five_turns():
"""Block for 5 turns."""
for i in range(5, 0, -1):
feed = yield f"Blocked for {i} turns"
def coroutine():
"""Yield a string containing the number sent. If 5 is sent, block for 5 turns."""
feed = yield 0
while True:
if feed == 5:
yield from wait_for_five_turns()
# "feed" is not up to date ! And it's logic, but bothersome.
feed = yield f"Received {feed}"
0 -> Received 0
1 -> Received 1
2 -> Received 2
3 -> Received 3
4 -> Received 4
5 -> Blocked for 5 turns
6 -> Blocked for 4 turns
7 -> Blocked for 3 turns
8 -> Blocked for 2 turns
9 -> Blocked for 1 turns
10 -> Received 5 <----- Not what I want
11 -> Received 11
12 -> Received 12
13 -> Received 13
14 -> Received 14
有没有办法检索 feed 的正确值?
或者也许是更好的重构方法?
祝你有个愉快的一天。
也可以 return 来自协程的值。在当前示例中,这将是:
def wait_for_five_turns():
"""Block for 5 turns."""
for i in range(5, 0, -1):
feed = yield f"Blocked for {i} turns"
return feed
def coroutine():
"""Yield a string containing the number sent. If 5 is sent, block for 5 turns."""
feed = yield 0
while True:
if feed == 5:
feed = yield from wait_for_five_turns()
feed = yield f"Received {feed}"
这会打印正确的预期输出:
0 -> Received 0
1 -> Received 1
2 -> Received 2
3 -> Received 3
4 -> Received 4
5 -> Blocked for 5 turns
6 -> Blocked for 4 turns
7 -> Blocked for 3 turns
8 -> Blocked for 2 turns
9 -> Blocked for 1 turns
10 -> Received 10 <-- Yeah.
11 -> Received 11
12 -> Received 12
13 -> Received 13
14 -> Received 14
我使用了错误的类型注释(Generator 类型提示的第 3 个元素),这让我认为协程只能 return None.
有关信息,这是这两个函数的类型提示:
def wait_for_five_turns() -> Generator[float, str, float]: ...
def coroutine() -> Generator[float, str, float]: ...
我想重构一个协同程序,将它的一些代码移到另一个function/coroutine。但是我需要在包含协程中检索它的最后一个提要,但我不知道如何正确地做到这一点。
这是一个更简单的协程示例。
def coroutine():
"""Yield a string containing the number sent. If 5 is sent, block for 5 turns."""
feed = yield 0
while True:
if feed == 5:
for i in range(5, 0, -1):
feed = yield f"Blocked for {i} turns"
feed = yield f"Received {feed}"
if __name__ == "__main__":
my_coroutine = coroutine()
next(my_coroutine) # Init the coroutine
# Print the coroutine results for inputs from 0 to 14
for j in range(15):
print(f"{j} -> {my_coroutine.send(j)}")
我期望(并得到)的结果是
0 -> Received 0
1 -> Received 1
2 -> Received 2
3 -> Received 3
4 -> Received 4
5 -> Blocked for 5 turns
6 -> Blocked for 4 turns
7 -> Blocked for 3 turns
8 -> Blocked for 2 turns
9 -> Blocked for 1 turns
10 -> Received 10
11 -> Received 11
12 -> Received 12
13 -> Received 13
14 -> Received 14
现在,我想通过将可重用部分移动到协程来改进我的代码 wait_for_five_turns
:
def wait_for_five_turns():
"""Block for 5 turns."""
for i in range(5, 0, -1):
feed = yield f"Blocked for {i} turns"
def coroutine():
"""Yield a string containing the number sent. If 5 is sent, block for 5 turns."""
feed = yield 0
while True:
if feed == 5:
yield from wait_for_five_turns()
# "feed" is not up to date ! And it's logic, but bothersome.
feed = yield f"Received {feed}"
0 -> Received 0
1 -> Received 1
2 -> Received 2
3 -> Received 3
4 -> Received 4
5 -> Blocked for 5 turns
6 -> Blocked for 4 turns
7 -> Blocked for 3 turns
8 -> Blocked for 2 turns
9 -> Blocked for 1 turns
10 -> Received 5 <----- Not what I want
11 -> Received 11
12 -> Received 12
13 -> Received 13
14 -> Received 14
有没有办法检索 feed 的正确值? 或者也许是更好的重构方法? 祝你有个愉快的一天。
也可以 return 来自协程的值。在当前示例中,这将是:
def wait_for_five_turns():
"""Block for 5 turns."""
for i in range(5, 0, -1):
feed = yield f"Blocked for {i} turns"
return feed
def coroutine():
"""Yield a string containing the number sent. If 5 is sent, block for 5 turns."""
feed = yield 0
while True:
if feed == 5:
feed = yield from wait_for_five_turns()
feed = yield f"Received {feed}"
这会打印正确的预期输出:
0 -> Received 0
1 -> Received 1
2 -> Received 2
3 -> Received 3
4 -> Received 4
5 -> Blocked for 5 turns
6 -> Blocked for 4 turns
7 -> Blocked for 3 turns
8 -> Blocked for 2 turns
9 -> Blocked for 1 turns
10 -> Received 10 <-- Yeah.
11 -> Received 11
12 -> Received 12
13 -> Received 13
14 -> Received 14
我使用了错误的类型注释(Generator 类型提示的第 3 个元素),这让我认为协程只能 return None.
有关信息,这是这两个函数的类型提示:
def wait_for_five_turns() -> Generator[float, str, float]: ...
def coroutine() -> Generator[float, str, float]: ...