Я пытаюсь предоставить подсказки типа для функции, которая принимает последовательность с одним из двух type
элементов, и я не знаю, как сделать mypy
счастливым. Пожалуйста, обратите внимание, что последовательность является однородной, то есть типы не могут быть смешаны, или-или. Обычно я делаю это, когда они являются «совместимыми» типами, например, объектом path str
или pathlib.Path
, и замечание, что с помощью Union
работает просто отлично. Но в случае последовательности Sequence[Union[..]]
(или Union[Sequence[..]]
), похоже, не работает. Вот минимальный рабочий пример:
from pathlib import Path
from typing import Sequence, Dict, Union
def fn_accepts_dict(adict):
"""Function from an external module that accepts `dict`s."""
for key, val in adict.items():
print(f"{key}, {val}")
def vararg_test(resources: Sequence[Union[str, Dict]]):
"""My function where I want to provide type hints"""
if isinstance(resources[0], str):
resources2 = [{"path": Path(f)} for f in resources]
else:
resources2 = resources
for d in resources2:
fn_accepts_dict(d)
Теперь, с вышеуказанными определениями, вызов vararg_test
с любой из этих двух работ, как и ожидалось:
l1 = ["foo/bar", "bar/baz"]
l2 = [{"path": Path("foo/bar")}, {"path": Path("bar/baz")}]
Но выполнение mypy
дает мне следующие ошибки:
type_hints.py:14: error: Argument 1 to "Path" has incompatible type "Union[str, Dict[Any, Any]]"; expected "Union[str, _PathLike[str]]"
type_hints.py:16: error: Incompatible types in assignment (expression has type "Sequence[Union[str, Dict[Any, Any]]]", variable has type "List[Dict[str, Path]]")
Found 2 errors in 1 file (checked 1 source file)
Как я могу решить эту проблему?
Редактировать : Чтобы дать некоторый фон, str
это путь, а dict
имеет метаданные, соответствующие этому пути, а функция fn_accepts_dict
объединяет метаданные в один объект метаданных. Так что логический поток у них либо: str -> dict -> fn_accepts_dict
, либо dict -> fn_accepts_dict
.
Хотя предложение @ ShadowRanger выглядело многообещающе, не повезло. Я получаю ту же ошибку со следующими подсказками:
def vararg_test2(resources: Union[Sequence[str], Sequence[Dict]]):
... # same implementation as above
mypy
ошибка:
type_hints.py:24: error: Argument 1 to "Path" has incompatible type "Union[str, Dict[Any, Any]]"; expected "Union[str, _PathLike[str]]"
type_hints.py:26: error: Incompatible types in assignment (expression has type "Union[Sequence[str], Sequence[Dict[Any, Any]]]", variable has type "List[Dict[str, Path]]")
Редактировать 2 : к сожалению, со всеми аннотациями это больше похоже на C / C ++, чем на Python; см. мой собственный ответ ниже для более полного решения Pythoni c.