def decorator(
wrapped: Union[
Callable[[], T],
Callable[[], Generator[T, None, None]]
]
) -> Callable[[], T]:
def wrapper():
value = wrapped()
if inspect.isgenerator(value):
return next(value)
else:
return value
return wrapper
@decorator
def foo() -> Generator[str, None, None]:
yield "bar"
上面的代碼在mypy中產生以下錯誤
error: Argument 1 to "decorator" has incompatible type "Callable[[], Generator[str, None, None]]"; expected "Callable[[], Generator[<nothing>, None, None]]"
這是 mypy 的限制還是我做錯了什么?
uj5u.com熱心網友回復:
這確實是一個錯誤。除錯后,我發現如果您顯式設定T泛型:
U = Union[int, float, str] # your target types here
T = TypeVar('T', U, None)
或者
T = TypeVar('T', None, Any)
它按預期作業。如果我設定Any,它必須是第二個引數,但是對于聯合或標量型別,它正在針對第一個引數進行測驗。
這是他們 GitHub 專案上的幾個相關問題:
- 模擬 GADT 時推斷
<nothing>在更具體的背景關系中使用時,型別變數設定為不與更具體的變數統一
更新:更多的除錯
基本上,如果我們撰寫TypeVar而不指定Any:
T = TypeVar('T', Type1, Type2, Type3, ...)
預期的引數將僅用第一種型別替換 T Type1。
error: Argument 1 to "decorator" has incompatible type "Callable[[], Generator[str, None, None]]"; expected "Union[Callable[[], Type1], Callable[[], Generator[Type1, None, None]]]"
但如果你這樣做:
T = TypeVar('T', Type1, Type2, Type3, Any)
它將忽略所有內容并Any直接進入,沒有錯誤。放置任意數量的Any's:
T = TypeVar('T', Any, Any, ..., Any, Type1, Type2, Type3)
將導致忽略所有以前的Any型別,并Type1再次檢查,就像根本沒有它們一樣。但是,如果您沒有任何TypeVar定義:
T = TypeVar('T')
您收到<nothing>預期的生成器輸出。
回復評論
有沒有辦法定義一個基本上涵蓋所有內容的型別變數,除了
Generator?我很難找到一個允許任何類的實體但不允許生成器的定義。
基本上,沒有。來自PEP 484:
沒有建議列出顯式引發的例外的語法。目前,此功能唯一已知的用例是檔案化的,在這種情況下,建議將此資訊放在檔案字串中。
Stack Overflow 上也有很多關于此功能的問題:
- Python 型別提示例外
- 在 Python 型別注釋中排除型別
- 排除特定型別的型別提示
即使沒有這個錯誤,您仍然會收到與定義相同的結果:
T = TypeVar('T', None, Any)
,因為你的TypeVar定義是空的,這在邏輯上應該相當于(來自 docs):
T = TypeVar('T') # Can be anything
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/394606.html
上一篇:在Rust中,如何組合兩個相同的函式,但一個接受&Vec<String>而另一個接受&Vec<&String>?
