Search code examples
pythonpycharmpython-typing

Type inference for class derived from Mapping


I have a class implementing MutableMapping

V = TypeVar('V')
K = TypeVar('K')
class MM(MutableMapping[K, V]):
    def __getitem__(self, k):
        return 1

    def __setitem__(self, k, v):
        pass

    def __delitem__(self, k):
        pass

    def __iter__(self):
        return iter(())

    def __len__(self):
        return 0

which gets used like this:

test: MM[str, int] = MM()
test["a"] = 1
var = test["a"]

The variable var should be of type int (according to the type hint), yet pycharm tells me that its type cannot be inferred.

example

Is this a bug in pycharm or is there something I am doing wrong?

Another thing that is surprising is that when I change the class definition to

MM(MutableMapping[str, V])

Pycharm indicates that the type of var is string. What am I missing?


Solution

  • You probably need to add type hints to each of your methods. For example:

    from typing import MutableMapping, TypeVar, Iterator
    
    K = TypeVar('K')
    V = TypeVar('V')
    
    class MM(MutableMapping[K, V]):
        def __getitem__(self, k: K) -> V:
            return ???
    
        def __setitem__(self, k: K, v: V) -> None:
            pass
    
        def __delitem__(self, k: K) -> None:
            pass
    
        def __iter__(self) -> Iterator[K]:
            return iter(())
    
        def __len__(self) -> int:
            return 0
    

    While I'm not 100% how exactly Pycharm's inference engine works, it seems reasonable to me that if you leave your functions untyped, it'll just default to assuming you meant to leave that function dynamically typed and that your params/return values are of type 'Any'.