I'm trying to define a class that takes another class as an attribute _model
and will instantiate objects of that class.
from abc import ABC
from typing import Generic, TypeVar, Any, ClassVar, Type
Item = TypeVar("Item", bound=Any)
class SomeClass(Generic[Item], ABC):
_model: ClassVar[Type[Item]]
def _compose_item(self, **attrs: Any) -> Item:
return self._model(**attrs)
I think it should be obvious that self._model(**attrs)
returns an instance of Item
, since _model
is explicitly declared as Type[Item]
and attrs
is declared as Dict[str, Any]
.
But what I'm getting from mypy 0.910
is:
test.py: note: In member "_compose_item" of class "SomeClass":
test.py:11: error: Returning Any from function declared to return "Item"
return self._model(**attrs)
^
What am I doing wrong?
You can use a special comment # type: ignore[code, ...] to only ignore errors with a specific error code (or codes) on a particular line. This can be used even if you have not configured mypy to show error codes. Currently it's only possible to disable arbitrary error codes on individual lines using this comment.
“Mypy is an optional static type checker for Python that aims to combine the benefits of dynamic (or 'duck') typing and static typing. Mypy combines the expressive power and convenience of Python with a powerful type system and compile-time type checking.” A little background on the Mypy project.
Again, mypy will not report any errors. The type of foo.bar is str, and mypy reasons that it can never be None. Hence the assert statement will always fail and the statement below will never be executed. (Note that in Python, None is not an empty reference but an object of type None .)
Statically typed code is often identical to normal Python code (except for type annotations), but sometimes you need to do things slightly differently. If installation fails, you’ve probably hit one of these issues: Mypy needs Python 3.5 or later to run. You may have to run pip like this: python3 -m pip install mypy.
Mypy can usually infer the types correctly when using isinstance type tests, but for other kinds of checks you may need to add an explicit type cast: def f(o: object) -> None: if type(o) is int: o = cast(int, o) g(o + 1) # This would be an error without the cast ... else: ...
(Note that in Python, None is not an empty reference but an object of type None .) In this example mypy will go on to check the last line and report an error, since mypy thinks that the condition could be either True or False: If you use the --warn-unreachable flag, mypy will generate an error about each unreachable code block.
MyPy can sometimes be a bit funny about the types of classes. You can solve this by specifying _model
as Callable[..., Item]
(which, after all, isn't a lie) instead of Type[Item]
:
from abc import ABC
from typing import Generic, TypeVar, Any, ClassVar, Callable
Item = TypeVar("Item")
class SomeClass(Generic[Item], ABC):
_model: ClassVar[Callable[..., Item]]
def _compose_item(self, **attrs: Any) -> Item:
return self._model(**attrs)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With