[英]mypy complains: function type annotation with Type[TypeVar['T', str, date]] and T output: Incompatible return value type (got "str", expected "date")
[英]How to deal with "Incompatible return value type (got overloaded function)" issue
我正在嘗試定義一個返回另一個函數的函數。 它返回的函數是重載的。
例如:
from typing import overload, Union, Callable
@overload
def foo(a: str) -> str:
pass
@overload
def foo(a: int) -> int:
pass
def foo(a: Union[str, int]) -> Union[str, int]:
if isinstance(a, int):
return 1
else:
# str
return "one"
def bar() -> Callable[[Union[str, int]], Union[str, int]]:
return foo # Incompatible return value type (got overloaded function, expected "Callable[[Union[str, int]], Union[str, int]]")
但是,我在功能bar
輸入是使用 Mypy 時出現的錯誤。
如何正確鍵入bar
? 我究竟做錯了什么?
這里的問題部分在於Callable
類型有點過於受限,無法准確表達foo
的類型,部分在於 mypy 目前在分析與 Callables 重載的兼容性時非常保守。 (在一般情況下很難做到)。
目前最好的方法可能是通過使用回調協議定義更精確的返回類型並返回它:
例如:
from typing import overload, Union, Callable
# Or if you're using Python 3.8+, just 'from typing import Protocol'
from typing_extensions import Protocol
# A callback protocol encoding the exact signature you want to return
class FooLike(Protocol):
@overload
def __call__(self, a: str) -> str: ...
@overload
def __call__(self, a: int) -> int: ...
def __call__(self, a: Union[str, int]) -> Union[str, int]: ...
@overload
def foo(a: str) -> str:
pass
@overload
def foo(a: int) -> int:
pass
def foo(a: Union[str, int]) -> Union[str, int]:
if isinstance(a, int):
return 1
else:
# str
return "one"
def bar() -> FooLike:
return foo # now type-checks
注意:從 Python 3.8 開始, Protocol
已添加到typing
模塊中。 如果您希望在早期版本的 Python 中使用它,請安裝typing_extensions module (
pip install typing_extensions`)並從那里導入它。
不得不像這樣復制簽名兩次無疑有點笨拙。 人們似乎普遍同意這是一個問題(在打字和mypy問題跟蹤器中有各種關於此的問題),但我認為對於如何最好地解決這個問題還沒有達成任何共識。
我通過更改為 pyre 來解決這個問題:
from typing import overload, Union
def foo(a: Union[str, int]) -> Union[str, int]:
if isinstance(a, int):
return 1
else:
return 'a string'
查看:
(.penv) nick$: pyre check
ƛ No type errors found
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.