我有以下工作代码来解决2021年代码降临节第1天的问题(由于itertools.pairwise,需要Python 3.10(,但我一直纠结于如何正确添加类型提示。
from itertools import pairwise, tee
from typing import Iterator, TypeVar, Tuple, Generator
_T_co = TypeVar("_T_co", covariant=True)
def tripletwise(iterable: Iterator[_T_co]) -> zip[Tuple[_T_co, _T_co, _T_co]]:
"""tripletwise('ABCDEFG') --> ABC BCD CDE DEF EFG"""
a, b, c = tee(iterable, 3)
next(b, None)
next(c, None)
next(c, None)
return zip(a, b, c)
def sonar_sweep(sea_floor_depths: Generator[int, None, None], part: int = 1) -> int:
if part == 1:
return sum(b > a for a, b in pairwise(sea_floor_depths))
return sonar_sweep((a + b + c for a, b, c in tripletwise(sea_floor_depths)), part=1)
def sea_floor_depths(report: str) -> Generator[int, None, None]:
return map(int, report.splitlines())
def main(part: int = 1) -> int:
with open("2021/data/day01.txt") as f:
report = f.read()
return sonar_sweep(sea_floor_depths(report), part)
if __name__ == "__main__":
report = """199
200
208
210
200
207
240
269
260
263"""
assert sonar_sweep(sea_floor_depths(report), part=1) == 7
assert sonar_sweep(sea_floor_depths(report), part=2) == 5
assert list(tripletwise("ABCDEFG")) == [
("A", "B", "C"),
("B", "C", "D"),
("C", "D", "E"),
("D", "E", "F"),
("E", "F", "G"),
]
assert list(tripletwise(sea_floor_depths(report))) == [
(199, 200, 208),
(200, 208, 210),
(208, 210, 200),
(210, 200, 207),
(200, 207, 240),
(207, 240, 269),
(240, 269, 260),
(269, 260, 263),
]
print(main())
print(main(part=2))
目前,当我在上面运行mypy时,我得到:
2021/day01.py:22: error: Incompatible return value type (got "map[int]", expected "Generator[int, None, None]")
2021/day01.py:44: error: Argument 1 to "tripletwise" has incompatible type "str"; expected "Iterator[<nothing>]"
我想用类型提示表明tripletwise()
可以接受任何可迭代的(例如字符串"ABCDEFG"
或sea_floor_depths(report)
的输出(。我也不确定sea_floor_depths()
的正确返回类型。
对于第一个错误,map
内建仅被记录为返回迭代器,因此您可以使用的最具体的类型提示是Iterator[int]
。Generator
是Iterator
的一个子类型,它仅在使用生成器表达式或生成器函数时出现,而您的函数没有。
对于第二个错误,问题是str
本身不是迭代器,而只是可迭代的,因此适当的类型提示应该是Iterable[_T_co]
。