2 回答

TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超4個(gè)贊
我認(rèn)為發(fā)生錯(cuò)誤是因?yàn)轭愋蜋z查器沒有足夠的信息來通過查看輸入?yún)?shù)的類型來推斷返回類型。雖然處理可能會(huì)有所改善。
假設(shè)你有一個(gè)簡(jiǎn)單的泛型函數(shù):
Enums = TypeVar("Enums", Enum1, Enum2)
def add(x: Enums, y: Enums) -> Enums:
return x
類型檢查器可以通過輸入?yún)?shù)的類型推斷返回類型:
add(Enum2.MEMBER3, Enum2.MEMBER4) # ok, return Enum2
add(Enum1.MEMBER1, Enum1.MEMBER2) # ok, return Enum1
add(Enum2.MEMBER3, Enum1.MEMBER2) # not ok
再次查看您的函數(shù)_enum_to_num,類型檢查器無法推斷返回類型,它只是不知道將返回什么類型,因?yàn)樗恢缹⒎祷厥裁搭愋蚦ast_enum:
def _enum_to_num(val: int, cast_enum: EnumMeta) -> Enums:
return cast_enum(val)
靜態(tài)類型檢查的想法是它在不執(zhí)行的情況下評(píng)估代碼,它調(diào)查變量的類型,而不是動(dòng)態(tài)值。通過查看 的類型cast_enum,即EnumMeta,類型檢查器無法判斷是否cast_enum會(huì)返回Enums??雌饋硭皇羌僭O(shè)它會(huì)返回Enum1,它會(huì)導(dǎo)致_enum_to_num(val, Enum2).
你知道它_enum_to_num(val, Enum2)會(huì)返回Enum2,因?yàn)槟阒纈s的值。該值是類型檢查器通常不會(huì)觸及的東西??赡軙?huì)造成混淆,變量的值是,而類型是,雖然是類型。cast_enumEnum2cast_enumEnum2cast_enumEnumMetaEnum2
這個(gè)問題可以通過告訴類型檢查器類型將通過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)
錯(cuò)誤將消失,因?yàn)楝F(xiàn)在類型檢查器可以推斷返回類型。

TA貢獻(xiàn)1847條經(jīng)驗(yàn) 獲得超7個(gè)贊
我首先寫一點(diǎn)關(guān)于 mypy 看到和報(bào)告的內(nèi)容,然后提出這是否是 mypy 錯(cuò)誤的問題。
消息:
Incompatible return value type (got "Enum1", expected "Enum2")
這里的意思是粗略地認(rèn)為它的一個(gè)Enum2
或一個(gè)子類型是預(yù)期的。Enum2
是聲明的返回值get_another_enum()
。但是 mypy 認(rèn)為函數(shù)調(diào)用_enum_to_num()
正在返回一個(gè)Enum1
類型。
Any
“大致”部分是因?yàn)楫?dāng)類型未綁定、或?yàn)椤⒒蝾愋蜁r(shí),類型檢查存在異常Union
;但這不適用于此示例。
Mypy 決定cast_enum()
in中的函數(shù)_enum_to_num()
返回列出的第一個(gè)Enums
類型——我想作為一個(gè)靜態(tài)類型檢查器,它必須選擇一個(gè),這就是它的作用。
因此,如果您在Enums
作業(yè)中切換順序并編寫:
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()
函數(shù)在這里找不到動(dòng)態(tài)類型錯(cuò)誤;運(yùn)行代碼也按預(yù)期工作。
另一方面,無論是在編譯時(shí)還是在運(yùn)行時(shí),Python 都不會(huì)檢查返回類型:您可以將返回類型更改_enum_to_none()
為 beNone
并且就 Python 解釋器而言仍然有效。
然后問題歸結(jié)為:在 mypy 強(qiáng)加的靜態(tài)類型系統(tǒng)中,這是一個(gè)錯(cuò)誤嗎?(我不認(rèn)為 PEP 484、526 或其他數(shù)字試圖解決這個(gè)問題)。
更有資格的人應(yīng)該回答這個(gè)問題,這是否是一個(gè)應(yīng)該被靜態(tài)分析器捕獲的錯(cuò)誤,特別是 mypy。
請(qǐng)參閱 Ken Hung 的答案,以更明確地消除 mypy 的錯(cuò)誤。
添加回答
舉報(bào)