#python #type-hinting #mypy #python-typing #abstract-base-class
Вопрос:
Я пытаюсь определить класс, который принимает другой класс в качестве атрибута _model
и будет создавать экземпляры объектов этого класса.
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)
Я думаю , должно быть очевидно, что self._model(**attrs)
возвращает экземпляр Item
, так _model
как явно объявлен как Type[Item]
и attrs
объявлен как Dict[str, Any]
.
Но то, что я получаю от mypy 0.910
этого:
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)
^
Что я делаю не так?
Комментарии:
1. вы знаете
**attrs: Any
, что в любом случае теряется почти вся безопасность типа? Это связано с ответом Алекса: у__init__
изItem
может быть любая подпись. Подумывали ли вы о том, чтобы быть более конкретным, например, сCallable[[int, str, bool], Item]
(с соответствующими типами аргументов)?2. Это:
bound=Any
действительно не имеет никакого смысла… У него просто не должно быть привязки.Any
это особый тип, который в основном означает «не вводите, проверьте это». Я не думаю, что даже определено, как он должен работать в качестве привязки для типоразмера.3. Кроме того, какую версию mypy вы используете? На моей машине
mypy 0.910
на самом деле не жалуется… но, как я уже сказал, я не думаюItem = TypeVar("Item", bound=Any)
, что это четко определено4. @juanpa.arrivillaga вы получите ошибку , только если запустите MyPy с
--strict
настройкой (и вы получите ее, даже если не укажетеbound=Any
дляTypeVar
, что, я согласен, бессмысленно). mypy-play.net/…5. @AlexWaygood ну, вы получите совершенно другую ошибку, если удалите ее.
Ответ №1:
MyPy иногда может быть немного забавным в отношении типов классов. Вы можете решить эту проблему, указав _model
как Callable[..., Item]
(что, в конце концов, не является ложью) вместо 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)