Search code examples
pythonmypy

mypy with dictionary's get function


I have some code that looks like this:

di: dict[str, float]

max_val = max(di, key=di.get)

When running mypy on it, it complains

error: Argument "key" to "max" has incompatible type overloaded function; expected "Callable[[str], Union[SupportsDunderLT[Any], SupportsDunderGT[Any]]]"

My guess is that this is because the return type of di.get is Union[float, None] in general, but in this specific instance, it should always return a float since the function is only being called on keys from di. The three workarounds I've discovered are to define a custom lambda function, ignore the di.get call, or cast it as follows.

get_lambda = lambda key: di[key]
max_val = max(di, key=get_lambda)

# ---------

max_val = max(
    di,
    key=di.get,  # type: ignore [arg-type]
)

# ---------

from typing import cast, Callable

max_val = max(di, key=cast(Callable[[str], float], di.get))

Is there a more proper/standard way of letting mypy know that the get method will not be returning None?


Solution

  • The dunder (double underscore) member function __getitem__ of a dict object is what you want here:

    max(di, key=di.__getitem__) 
    

    raises no complains from mypy. The reason your lambda works is because it precisely emulates the intent of __getitem__, which is to implement evaluation of self[key], as explained in the documentation.