如何使用mypy来检查groupby结果对next()的使用情况?

时间:2016-06-29 03:55:54

标签: python mypy

我在我的项目中尝试使用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]]],对吗?

我错过了什么?

1 个答案:

答案 0 :(得分: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可能有用吗?