向接受任何可迭代并返回压缩值的函数添加类型提示

Posted

技术标签:

【中文标题】向接受任何可迭代并返回压缩值的函数添加类型提示【英文标题】:Add type hints to function that accepts any iterable and returns zipped values 【发布时间】:2022-01-08 11:47:25 【问题描述】:

我有以下工作代码来解决Advent of Code 2021 day 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() 的正确返回类型。

【问题讨论】:

【参考方案1】:

至于第一个错误,map 内置函数仅记录为返回一个迭代器,因此您可以使用的最具体的类型提示是 Iterator[int]GeneratorIterator 的子类型,仅在使用生成器表达式或生成器函数时出现,而您的函数不会。

对于第二个错误,问题在于strs 本身不是iterators,而只是iterables,所以适当的类型提示应该是Iterable[_T_co]

【讨论】:

以上是关于向接受任何可迭代并返回压缩值的函数添加类型提示的主要内容,如果未能解决你的问题,请参考以下文章

python-迭代器详解

Python中的迭代器

python学习--迭代器和异常处理

迭代器

迭代器与装饰器

迭代器