我在我的项目中尝试使用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]]]
,对吗?
我错过了什么?
答案 0 :(得分:1)
原因是type annotation for next
。 next
函数定义为具有以下类型签名:
@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可能有用吗?