2017-05-11 56 views
1

我的功能看起來像這樣簡單的代碼示例:Mypy錯誤 - 不兼容的類型分配

def my_func() -> dict: 
    result = {"success": False} 

    if condition: 
     result["success"] = True 
     return result 
    else: 
     result["message"] = "error message" 
    return result 

當我運行Mypy(0.52版),我得到這個錯誤:

error: Incompatible types in assignment (expression has type "str", target has type "bool") 

和誤差指向我的代碼示例中的第二行。 爲什麼mypy返回這個錯誤?是我的代碼無效(以任何方式)還是這是一些mypy錯誤?

回答

5

的問題是,mypy推斷,你result變量的類型是Dict[str, bool]由於您第一次初始化後第2行

因此,當你嘗試後插入一個海峽,mypy(理所當然)笙歌。您有幾個修復代碼的選項,我將按照最不安全的順序列出。

選項1是宣佈你的字典,它的值是Any型的 - 也就是你的值不會進行類型檢查都:我們需要註釋你的第二個

from typing import Any, Dict 

def my_func(condition: bool) -> Dict[str, Any]: 
    result = {"success": False} # type: Dict[str, Any] 

    if condition: 
     result["success"] = True 
    else: 
     result["message"] = "error message" 
    return result 

注請給mypy一個關於result應該是什麼類型的暗示,以幫助其推理過程。

如果您使用Python 3.6+,可以註釋使用以下替代語法那條線,它使用可變註釋(這是新的像Python 3.6):

result: Dict[str, Any] = {"success": False} 

選項2稍微更類型安全 - 使用Union聲明你的值是strs或bools,但沒有別的。這不完全類型安全,但至少你仍然可以有一些檢查您的字典。

from typing import Any, Dict 

def my_func(condition: bool) -> Dict[str, Union[str, bool]]: 
    result = {"success": False} # type: Dict[str, Union[str, bool]] 

    if condition: 
     result["success"] = True 
    else: 
     result["message"] = "error message" 
    return result 

你也許會發現類型的註釋是有點長/惱人的類型,所以你可以使用類型別名可讀性(並選擇使用變量註釋語法),像這樣:

ResultJson = Dict[str, Union[str, bool]] 

def my_func(condition: bool) -> ResultJson 
    result: ResultJson = {"success": False} 
    # ...snip... 

選項3是最安全的,雖然它確實要求您使用實驗'TypedDict'類型,它允許您指定特定類型到字典中的不同字段。也就是說,使用這種類型需要您自擔風險 - AFAIK尚未添加到PEP 484中,這意味着其他類型檢查工具(如Pycharm的檢查器)沒有義務理解這一點。 Mypy本身只是最近增加了對TypedDict支持,因此可能仍然是越野車:

from typing import Optional 
from mypy_extensions import TypedDict 

ResultJson = TypedDict('ReturnJson', {'success': bool, 'message': Optional[str]}) 

def my_func(condition: bool) -> ResultJson: 
    result = {"success": False, "message": None} # type: ResultJson 

    if condition: 
     result["success"] = True 
    else: 
     result["message"] = "error message" 
    return result 

一定要安裝mypy_extensions包,如果你想使用這個選項。

+0

感謝您的全面解答邁克爾!我認爲我爲mypy邏輯的某些概念而奮鬥,但你真的爲我清除了這個問題。旁註:當行數超過PEP8允許的79個字符時,您是否知道如何處理內聯類型提示? (我不能在這個項目中使用Python3.6,所以新的變量註釋語法不適用於我) –

+1

@JanRozycki謹慎使用[type aliases](http://mypy.readthedocs.io/en/latest/ types_of_types.html#type-aliases)通常可以幫助緩解這個問題。當用許多參數輸入函數時,輸入你的函數[像這樣](http://mypy.readthedocs.io/en/latest/python2.html#multi-line-python-2-function- annotations)也是有幫助的。 – Michael0x2a