Here are a couple of functions:
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 warns about the_dict.values()
in the last line:
Expected type 'Sequence[float]', got _dict_values[float, str] instead
But .. those values can be iterated across and have their length taken.
I tried
def avg(vals: Union[Sequence[float], _dict_values]):
which seems insane, but also didn't work.
Suggestions?
I can turn off the typing for that arg, but I am curious what the right thing is.
CodePudding user response:
_dict_values
is not a Sequence
(it's closer to an Iterator
). Lucky avg
doesn't require everything Sequence
ensures. You only need Iterable[float]
for sum
and Sized
for len()
.
from typing import Iterable, Protocol, Sized
class SupportsFloatMean(Iterable[float], Sized, Protocol):
...
def avg(vals: SupportsFloatMean):
return sum(val for val in vals) / len(vals)
CodePudding user response:
Reference: https://docs.python.org/3/library/stdtypes.html?highlight=dict#dictionary-view-objects
The objects returned by
dict.keys()
,dict.values()
anddict.items()
are view objects. Dictionary views can be iterated over to yield their respective data, and support membership tests.
iter(dictview)
: Return an iterator over the keys, values or items (represented as tuples of (key, value)) in the dictionary.
from typing import Union, Iterable, Sized
def avg(vals: Union[Iterable[float], Sized]) -> float:
return sum(val for val in vals) / len(vals)
def foo() -> float:
the_dict = {'a': 1., 'b': 2.}
return avg(the_dict.values())
if __name__ == '__main__':
print(foo())