【问题标题】:How to type-check usage of next() with groupby result using mypy?如何使用 mypy 对 next() 的用法和 groupby 结果进行类型检查?
【发布时间】:2016-06-29 03:55:54
【问题描述】:

我正在我的项目中尝试 mypy 的一些 utils 函数,但我在使用这个结合了 groupby 和 next 的函数时遇到了问题。

这是功能代码:

from itertools import groupby
from typing import Iterable, Any


def all_same(iterable: Iterable[Any]) -> bool:
    """Return True if all elements in iterable are equal
    >>> all_same([3, 3, 3])
    True
    >>> all_same([3, 3, 1])
    False
    >>> all_same([])
    True
    >>> all_same(['a', 'a'])
    True
    """
    g = groupby(iterable)
    return bool(next(g, True)) and not bool(next(g, False))

我不断收到关于无法推断 type argument 1 of "next" 的错误:

$ mypy testing.py 
testing.py: note: In function "all_same":
testing.py:17: error: Cannot infer type argument 1 of "next"

我认为这意味着它无法在这里推断g 的类型,对吧?

我很难理解这是否是我的类型注释或groupby 的类型注释中的问题。

供参考,这里是the type annotation for groupby

@overload
def groupby(iterable: Iterable[_T]) -> Iterator[Tuple[_T, Iterator[_T]]]: ...

所以这意味着,“groupby 接受一个 T 类型的迭代器,并返回一个包含两个项目的元组迭代器:(一个 T 类型的项目,一个 T 类型的对象的迭代器)”。 对我来说看起来不错,但是 mypy 应该能够将next 的第一个参数推断为Iterator[Tuple[Any, Iterator[Any]]],对吧?

我错过了什么?

【问题讨论】:

    标签: python mypy


    【解决方案1】:

    原因是由于type annotation for nextnext 函数定义为具有以下类型签名:

    @overload
    def next(i: Iterator[_T]) -> _T: ...
    @overload
    def next(i: Iterator[_T], default: _T) -> _T: ...
    

    基本上,mypy 期望默认值的类型与迭代器中任何内容的类型相同。

    但是,g 将具有 Iterator[Tuple[Any, Iterator[Any]]] 类型,而 Tuple[Any, Iterator[Any]]bool 的类型不同。

    不幸的是,我不确定修复你的算法以进行类型检查的最佳方法是什么,因为next 的给定类型签名对我来说似乎很合理 + 似乎不太可能改变(尽管你可以归档如果你想支持这种改变,有什么问题吗?)。也许here 的答案可能有用?

    【讨论】:

    • 谢谢!由于渐进式输入,更改我的算法没有意义,但算法是合理的。
    • 这对我来说仍然很奇怪,因为错误是关于无法推断类型。
    • @elias - 嗯,问题是根据 mypy,你的算法 isn't 是正确的 - 你的代码,无论好坏,不尊重next 的类型签名。 mypy 抱怨无法推断类型的原因基本上源于这个问题——它试图协调不匹配,并因特定的错误消息而失败。但是,是的,mypy 正在报告 this 特定错误而不是“您的类型不匹配”错误这一事实很可能是一个错误。
    • 好吧,我拒绝更改算法,因为next类型注释,哈哈!我从 Raymond Hettinger(Python 核心开发人员)那里得到它,它非常好。 :) 感谢您将其挖掘到最后!
    猜你喜欢
    • 2020-03-17
    • 2012-10-16
    • 2016-09-02
    • 1970-01-01
    • 1970-01-01
    • 2019-01-19
    • 2020-10-29
    • 2021-11-23
    • 1970-01-01
    相关资源
    最近更新 更多