亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Python mypy 檢查 TypeVar(bound=Union[A, B]) 的返回類型不會

Python mypy 檢查 TypeVar(bound=Union[A, B]) 的返回類型不會

慕萊塢森 2022-10-18 16:08:06
我被困在試圖理解TypeVar以兩種不同方式使用它時的邊界:Enums = TypeVar("Enums", Enum1, Enum2)Enums = TypeVar("Enums", bound=Union[Enum1, Enum2])這是我正在使用的代碼:#!/usr/bin/env python3.6"""Figuring out why enum is saying incompatible return type."""from enum import IntEnum, EnumMetafrom typing import TypeVar, Unionclass Enum1(IntEnum):    MEMBER1 = 1    MEMBER2 = 2class Enum2(IntEnum):    MEMBER3 = 3    MEMBER4 = 4# Enums = TypeVar("Enums", bound=Union[Enum1, Enum2])  # Case 1... SuccessEnums = TypeVar("Enums", Enum1, Enum2)  # Case 2... error: Incompatible return valuedef _enum_to_num(val: int, cast_enum: EnumMeta) -> Enums:    return cast_enum(val)def get_some_enum(val: int) -> Enum1:    return _enum_to_num(val, Enum1)def get_another_enum(val: int) -> Enum2:    return _enum_to_num(val, Enum2)  # line 35運行時mypy==0.770:Case 1:Success: no issues foundCase 2:35: error: Incompatible return value type (got "Enum1", expected "Enum2")這種情況與這個問題非常相似:Difference between TypeVar('T', A, B) and TypeVar('T', bound=Union[A, B])答案解釋了使用案例 1( bound=Union[Enum1, Enum2]) 時,以下是合法的:Union[Enum1, Enum2]Enum1Enum2并且在使用案例 2 ( A, B) 時,以下是合法的:Enum1Enum2但是,我認為這個答案不能解釋我的問題,我沒有使用這種Union情況。誰能告訴我發生了什么事?
查看完整描述

2 回答

?
慕虎7371278

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)

錯誤將消失,因為現在類型檢查器可以推斷返回類型。


查看完整回答
反對 回復 2022-10-18
?
aluckdog

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 的錯誤。



查看完整回答
反對 回復 2022-10-18
  • 2 回答
  • 0 關注
  • 462 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號