2 回答

TA貢獻1802條經驗 獲得超4個贊
我認為發生錯誤是因為類型檢查器沒有足夠的信息來通過查看輸入參數的類型來推斷返回類型。雖然處理可能會有所改善。
假設你有一個簡單的泛型函數:
Enums = TypeVar("Enums", Enum1, Enum2)
def add(x: Enums, y: Enums) -> Enums:
return x
類型檢查器可以通過輸入參數的類型推斷返回類型:
add(Enum2.MEMBER3, Enum2.MEMBER4) # ok, return Enum2
add(Enum1.MEMBER1, Enum1.MEMBER2) # ok, return Enum1
add(Enum2.MEMBER3, Enum1.MEMBER2) # not ok
再次查看您的函數_enum_to_num,類型檢查器無法推斷返回類型,它只是不知道將返回什么類型,因為它不知道將返回什么類型cast_enum:
def _enum_to_num(val: int, cast_enum: EnumMeta) -> Enums:
return cast_enum(val)
靜態類型檢查的想法是它在不執行的情況下評估代碼,它調查變量的類型,而不是動態值。通過查看 的類型cast_enum,即EnumMeta,類型檢查器無法判斷是否cast_enum會返回Enums。看起來它只是假設它會返回Enum1,它會導致_enum_to_num(val, Enum2).
你知道它_enum_to_num(val, Enum2)會返回Enum2,因為你知道is的值。該值是類型檢查器通常不會觸及的東西??赡軙斐苫煜?,變量的值是,而類型是,雖然是類型。cast_enumEnum2cast_enumEnum2cast_enumEnumMetaEnum2
這個問題可以通過告訴類型檢查器類型將通過cast_enum使用來解決typing.Type:
from typing import TypeVar, Union, Type
...
def _enum_to_num(val: int, cast_enum: Type[Enums]) -> Enums:
return cast_enum(val)
錯誤將消失,因為現在類型檢查器可以推斷返回類型。

TA貢獻1847條經驗 獲得超7個贊
我首先寫一點關于 mypy 看到和報告的內容,然后提出這是否是 mypy 錯誤的問題。
消息:
Incompatible return value type (got "Enum1", expected "Enum2")
這里的意思是粗略地認為它的一個Enum2
或一個子類型是預期的。Enum2
是聲明的返回值get_another_enum()
。但是 mypy 認為函數調用_enum_to_num()
正在返回一個Enum1
類型。
Any
“大致”部分是因為當類型未綁定、或為、或類型時,類型檢查存在異常Union
;但這不適用于此示例。
Mypy 決定cast_enum()
in中的函數_enum_to_num()
返回列出的第一個Enums
類型——我想作為一個靜態類型檢查器,它必須選擇一個,這就是它的作用。
因此,如果您在Enums
作業中切換順序并編寫:
Enums = TypeVar("Enums", Enum2, Enum1) # Case 2... error: Incompatible return value
然后第 35 行將成功,但返回get_some_enum()
將失敗并顯示以下消息:
error: Incompatible return value type (got "Enum2", expected "Enum1")
至于這是否是mypy的bug,很難說……
type()
使用orininstance()
函數在這里找不到動態類型錯誤;運行代碼也按預期工作。
另一方面,無論是在編譯時還是在運行時,Python 都不會檢查返回類型:您可以將返回類型更改_enum_to_none()
為 beNone
并且就 Python 解釋器而言仍然有效。
然后問題歸結為:在 mypy 強加的靜態類型系統中,這是一個錯誤嗎?(我不認為 PEP 484、526 或其他數字試圖解決這個問題)。
更有資格的人應該回答這個問題,這是否是一個應該被靜態分析器捕獲的錯誤,特別是 mypy。
請參閱 Ken Hung 的答案,以更明確地消除 mypy 的錯誤。
添加回答
舉報