下面是几个函数:
from typing import Sequence
def avg(vals: Sequence[float]):
return sum(val for val in vals) / len(vals)
def foo():
the_dict = {'a': 1., 'b': 2.}
return avg(the_dict.values())
PyCharm 2022.3在最后一行警告了the_dict.values()
:
应为类型"Sequence [float]",但得到了_dict_values [float,str]
但是这些值可以被迭代,并取其长度。
我试过了
from typing import Sequence, Union
def avg(vals: Union[Sequence[float], _dict_values]):
...
这听起来很疯狂,但也没起作用
建议?
我可以关闭该参数的类型,但我很好奇什么是正确的注解。
2条答案
按热度按时间u3r8eeie1#
_dict_values
不是Sequence
(它更接近于Iterator
),幸运的avg
并不需要Sequence
确保的所有东西,你只需要Iterable[float]
来实现sum
,Sized
来实现len()
。gmol16392#
如果你想让
avg
函数兼容最广泛的类型,你只需要一个支持Iterable
协议(用在for
-loop中)和Sized
协议(用在len
函数中)的类型,不幸的是,这两个协议都不能从另一个继承,正如你在这里看到的。因此,您需要创建这两者的交集,这可以通过PEP544中提到的
typing.Protocol
实现(在本例中),@PeterSutton的回答中也使用了这一点。如果你不想太冗长,不需要自定义协议,并且 * 几乎 * 一样广泛,你可以简单地使用
Collection
ABC。它继承自Iterable
和Sized
以及Container
。后者定义了__contains__
方法,这意味着你可以用它来做in
检查。从技术上讲,在avg
函数中并不需要它。很明显,
Collection
仍然是ValuesView
的超类,正如您在这里看到的,因此您可以毫无困难地使用dict.values
调用avg
。另外,不要忘记返回类型注解。-)