Search code examples
pythonmypypython-typingpython-3.10

Is there any way to override inherited class attribute type in python with mypy?


I wrote a defaultdict subclass that can call default_factory with key as argument.

from collections import defaultdict
from typing import TypeVar, Any, Callable, Generic

K = TypeVar('K')


class keydefaultdict(defaultdict, Generic[K]):
    ''' Drop-in replacement for defaultdict accepting key as argument '''

    default_factory: Callable[[], Any] | Callable[[K], Any] | None

    def __missing__(self, key: K) -> Any:
        if self.default_factory is None:
            raise KeyError(key)
        else:
            try:
                ret = self[key] = self.default_factory(key)
            except TypeError:  # try no-key signature
                ret = self[key] = self.default_factory()
            # if failed, let the error propagate as usual

            return ret

mypy complains on the default_factory type hint:

incompatible type in assignment (expression has type "Callable[[], Any] | Callable[[K], Any] | None", base class "defaultdict" defined the type as "Optional[Callable[[], Any]]")

Is there any way to override the type? mypy complains also on this lines self.default_factory(...) - too many arguments (or too few arguments) and in places where this dict is instantiated (incompatible type):

data = keydefaultdict(lambda key: [key])

Argument 1 to "keydefaultdict" has incompatible type "Callable[[Any], list[Any]]"; expected "Optional[Callable[[], Any]]"


Solution

  • This is intended behavior, as what you're describing violates the Liskov substitution principle. See the mypy documentation for more details.

    Using defaultdict as a subclass is a bad idea for this reason. But, if you really want to get around this (not recommended), you can use # type: ignore[override], like so:

    default_factory: Callable[[], Any] | Callable[[K], Any] | None # type: ignore[override]
    

    This is described in further detail in the mypy documentation if you want more information.