在阅读了Eli Bendersky的文章关于通过Python协程实现状态机后,我想...
- 看到他的示例在Python3下运行
- 并且为生成器添加适当的类型注释
我已经成功完成了第一部分(但没有使用async def
或yield from
,我基本上只是将代码进行移植 - 所以任何改进都非常欢迎)。
但是我需要一些帮助来为协程添加类型注释:
#!/usr/bin/env python3
from typing import Callable, Generator
def unwrap_protocol(header: int=0x61,
footer: int=0x62,
dle: int=0xAB,
after_dle_func: Callable[[int], int]=lambda x: x,
target: Generator=None) -> Generator:
""" Simplified protocol unwrapping co-routine."""
#
# Outer loop looking for a frame header
#
while True:
byte = (yield)
frame = [] # type: List[int]
if byte == header:
#
# Capture the full frame
#
while True:
byte = (yield)
if byte == footer:
target.send(frame)
break
elif byte == dle:
byte = (yield)
frame.append(after_dle_func(byte))
else:
frame.append(byte)
def frame_receiver() -> Generator:
""" A simple co-routine "sink" for receiving full frames."""
while True:
frame = (yield)
print('Got frame:', ''.join('%02x' % x for x in frame))
bytestream = bytes(
bytearray((0x70, 0x24,
0x61, 0x99, 0xAF, 0xD1, 0x62,
0x56, 0x62,
0x61, 0xAB, 0xAB, 0x14, 0x62,
0x7)))
frame_consumer = frame_receiver()
next(frame_consumer) # Get to the yield
unwrapper = unwrap_protocol(target=frame_consumer)
next(unwrapper) # Get to the yield
for byte in bytestream:
unwrapper.send(byte)
这段代码正常运行...
$ ./decoder.py
Got frame: 99afd1
Got frame: ab14
...并进行类型检查:
$ mypy --disallow-untyped-defs decoder.py
$
但我相信我可以做得比仅使用 Generator
基类在类型规范中更好(就像我为 Callable
所做的那样)。我知道它需要 3 个类型参数(Generator[A,B,C]
),但我不确定它们在这里应该如何指定。
任何帮助都非常欢迎。
async def
及相关内容 -- 目前它们还不被 mypy 支持,但正在积极开发/预计将在不久的将来准备好!有关更多细节,请参见 https://github.com/python/mypy/pull/1808 和 https://github.com/python/mypy/issues/1886。 - Michael0x2a