Why does mypy complain about Any as return annotation and how should I annotate a return value that can be anything?
Question:
I have a class that is essentially a wrapper around a dictionary:
class Wrapper(dict):
...
def __getitem__(self, item: Hashable) -> Any:
return self.wrapped[item]
When checking the annotations with mypy
, it yields an Explicit "Any" is not allowed
when checking this code. My guess is that this stems from the concept that Any
is the ancestor and successor of all other types. How should I annotate such function where I want to allow anything to be returned?
Answers:
This happens when the disallow_any_explicit
is set to True
for that module in the configuration file. Just remove that option for the default False
.
You have provided insufficient information in the question to recreate this error but if your sole question is:
How should I annotate such function where I want to allow anything to be returned?
The simple answer is don’t annotate it at all. It will by default act as Any
.
We need to tell mypy
that types of self.wrapped
container are related to the ones of Wrapper
methods, we can do that using typing.TypeVar
instances for keys and values in our case.
So we can end up with something like
from collections import abc
from typing import (Dict,
Iterator,
TypeVar)
class Wrapper(abc.MutableMapping):
KeyType = TypeVar('KeyType')
ValueType = TypeVar('ValueType')
def __init__(self, wrapped: Dict[KeyType, ValueType]) -> None:
self.wrapped = wrapped
def __delitem__(self, key: KeyType) -> None:
del self.wrapped[key]
def __len__(self) -> int:
return len(self.wrapped)
def __iter__(self) -> Iterator[KeyType]:
return iter(self.wrapped)
def __setitem__(self, key: KeyType, value: ValueType) -> None:
self.wrapped[key] = value
def __getitem__(self, key: KeyType) -> ValueType:
return self.wrapped[key]
Test
Running mypy
with --disallow-any-explicit
flag causes no errors/warnings.
Note about inheritance/composition
If one really needs a custom mapping I’ll recommend to not mix inheritance from dict
with using self.wrapped
dict
-field as it can cause a lot of pain in the future (we should re-define all of its methods or sometimes you will be using self.wrapped
and sometimes not).
We can simply use MutableMapping
ABC from collections.abc
module and define basic methods (like __getitem__
), the rest (keys()
, values
, items()
are defined already).
I have a class that is essentially a wrapper around a dictionary:
class Wrapper(dict):
...
def __getitem__(self, item: Hashable) -> Any:
return self.wrapped[item]
When checking the annotations with mypy
, it yields an Explicit "Any" is not allowed
when checking this code. My guess is that this stems from the concept that Any
is the ancestor and successor of all other types. How should I annotate such function where I want to allow anything to be returned?
This happens when the disallow_any_explicit
is set to True
for that module in the configuration file. Just remove that option for the default False
.
You have provided insufficient information in the question to recreate this error but if your sole question is:
How should I annotate such function where I want to allow anything to be returned?
The simple answer is don’t annotate it at all. It will by default act as Any
.
We need to tell mypy
that types of self.wrapped
container are related to the ones of Wrapper
methods, we can do that using typing.TypeVar
instances for keys and values in our case.
So we can end up with something like
from collections import abc
from typing import (Dict,
Iterator,
TypeVar)
class Wrapper(abc.MutableMapping):
KeyType = TypeVar('KeyType')
ValueType = TypeVar('ValueType')
def __init__(self, wrapped: Dict[KeyType, ValueType]) -> None:
self.wrapped = wrapped
def __delitem__(self, key: KeyType) -> None:
del self.wrapped[key]
def __len__(self) -> int:
return len(self.wrapped)
def __iter__(self) -> Iterator[KeyType]:
return iter(self.wrapped)
def __setitem__(self, key: KeyType, value: ValueType) -> None:
self.wrapped[key] = value
def __getitem__(self, key: KeyType) -> ValueType:
return self.wrapped[key]
Test
Running mypy
with --disallow-any-explicit
flag causes no errors/warnings.
Note about inheritance/composition
If one really needs a custom mapping I’ll recommend to not mix inheritance from dict
with using self.wrapped
dict
-field as it can cause a lot of pain in the future (we should re-define all of its methods or sometimes you will be using self.wrapped
and sometimes not).
We can simply use MutableMapping
ABC from collections.abc
module and define basic methods (like __getitem__
), the rest (keys()
, values
, items()
are defined already).