簡體   English   中英

如何幫助Mypy理解“如果不是這樣”的結構?

[英]How to help mypy understand “if isinstance else” structure?

我使用一種簡單的方法來處理可以是字符串或字符串列表的參數。 它故意對錯誤沒有魯棒性,但卻是一種快速的方法。

該方法在普通的Python中可以正常工作,但是mypy不能很好地處理其類型並引發錯誤:

def dosomething(ext: Union[str, Iterable[str]] = ".txt"):
    exts: Tuple[str, ...] = (ext, ) if isinstance(ext, str) else ext

錯誤: Incompatible types in assignment (expression has type "object", variable has type "Tuple[str, ...]")

調查此問題,我發現mypy無法使用if isinstance else結構減少可用的類型選項:

def dosomething(ext: Union[str, Iterable[str]] = ".txt"):
    exts = (ext, ) if isinstance(ext, str) else ext
    reveal_type(exts)  # Revealed type is 'builtins.object'

看到mypy退回到object對我來說是一個驚喜,但是我懷疑這可能是因為str也是Iterable[str]

我想找到一種方法來避免這種意外情況,方法是在保持簡單性的同時幫助mypy。

這歸結為mypy如何為條件表達式推斷類型的問題。 在簡單的上下文中,表達式a if predicate else b推斷為ab的超類型。 strIterable[str]的情況下,這是builtins.object

x = reveal_type(1 if bool() else "str")
# Revealed type is 'builtins.object'

一個例外是,如果mypy可以將謂詞解析為True或False,則將類型縮小為正確的分支:

x = reveal_type(1 if True else "str")
# Revealed type is 'builtins.int'

有人希望mypy可以將isinstance檢查解析為True或False,但是似乎尚未實現。 我認為這將是一個非常合理的功能要求。

但是,我們可以利用條件表達式類型的一個不錯的功能,那就是它可以識別上下文。 因此,如果在期望使用其他類型的上下文中使用條件表達式,並且條件的兩端都滿足該類型,則類型檢查將通過。 這已經討論過這里的聯盟類型的范圍內,但在你的情況下,兩個分支滿足Iterable[str]

exts: Iterable[str] = (ext, ) if isinstance(ext, str) else ext

因此,關鍵只是明確指定exts的類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM