2017-05-11 7 views
1

Meine Funktion sieht wie folgt aus vereinfachte Codebeispiel:Mypy Fehler - inkompatible Typen in Zuordnung

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

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

Wenn ich Mypy (Version 0.52) laufen bekomme ich diesen Fehler:

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

und der Fehler auf die vorletzte Zeile in meinem Codebeispiel zeigen. Warum Mypy diesen Fehler zurückgibt? Ist mein Code ungültig (in irgendeiner Weise) oder ist das ein Mypy Bug?

Antwort

5

Das Problem ist, dass mypy gefolgert, dass die Art Ihrer result Variable ist Dict[str, bool] darauf zurückzuführen, wie Sie zuerst 2. initialisiert es auf der Leitung

Folglich wird, wenn Sie versuchen, eine str einfügen später mypy (zu Recht) beschwert . Sie haben mehrere Möglichkeiten, Ihren Code zu reparieren, den ich in der Reihenfolge der am wenigsten typensicheren Listen auflisten werde.

Option 1 ist Ihr Wörterbuch zu erklären, dass seine Werte vom Typ sind Any - das heißt, Ihre Werte nicht typgeprüft werden überhaupt:

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 

Bitte beachte, dass wir benötigt, um Ihre zweite mit Anmerkungen versehen Linie, um Mypy einen Hinweis darauf zu geben, was der Typ von result sein sollte, um seinen Inferenzprozess zu unterstützen.

Wenn Sie Python verwenden 3.6+, können Sie diese Zeile mit Anmerkungen versehen kann die folgende alternative Syntax verwendet, die variable Anmerkungen (die als von Python 3.6 neu sind) verwendet:

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

2 Option ist etwas mehr type-safe - deklarieren Sie Ihre Werte entweder als strs oder bools, aber sonst nicht als Union. Dies ist nicht vollständig typsicher, aber zumindest können Sie immer noch einige Prüfungen auf Ihrem Diktat haben.

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 

Sie vielleicht, dass Typenannotation finden können ein wenig lang/lästig eintippen sein, so dass Sie Typ-Aliasnamen zur besseren Lesbarkeit verwenden könnten (und optional die variable Annotation Syntax), etwa so:

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

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

Option 3 ist am typsichersten, obwohl es erfordert erfordert, dass Sie den experimentellen "TypedDict" -Typ verwenden, mit dem Sie bestimmten Typen zu verschiedenen Feldern in Ihrem Dict zuweisen können. Das heißt, verwenden Sie diesen Typ auf eigenes Risiko - AFAIK wurde noch nicht zu PEP 484 hinzugefügt, was bedeutet, dass andere Typprüfwerkzeuge (wie Pycharms Checker) nicht verpflichtet sind, dies zu verstehen. Mypy selbst hinzugefügt erst vor kurzem Unterstützung für TypedDict, und so immer noch fehlerhaft sein kann:

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 

unbedingt das mypy_extensions Paket installieren, wenn Sie diese Option verwenden möchten.

+0

Danke für diese umfassende Antwort Michael! Ich denke, ich habe mit bestimmten Konzepten der Mypy-Logik gekämpft, aber du hast das wirklich für mich klar gemacht. Hinweis: Wissen Sie, wie Sie mit inline-Typ-Hinting-Kommentaren umgehen, wenn die Zeile länger als 79 von PEP8 erlaubte Zeichen ist? (Ich kann Python3.6 nicht für dieses Projekt verwenden, daher ist die neue Annotationssyntax für Variablen für mich nicht verfügbar) –

+1

@JanRozycki Vorsichtiger Gebrauch von [type aliase] (http://mypy.readthedocs.io/en/latest/ types_of_types.html # type-aliases kann normalerweise helfen, dieses Problem zu beheben.Wenn Sie Funktionen mit vielen Parametern eingeben, kann das Eingeben der Funktion [this this] (http://mypy.readthedocs.io/en/latest/python2.html#multi-line-python-2-function-annotations) hilfreich sein. – Michael0x2a

Verwandte Themen