2016-06-20 20 views
3

Ich verwende Python PEP484 Typ Hinweise, um einen Typ-Checker für eine DSL zu schreiben, die ich in Python geschrieben habe. Wenn ich eine Funktion erwarte, die für eines ihrer Argumente den Typ T erwartet und mit einem Ausdruck vom Typ S aufgerufen wird, wie kann ich dann überprüfen, ob der Aufruf gültig ist? Verwendet issubclass(S, T) genug? Wenn ja, warum hat mypy eine so komplizierte is_subtype Prüfung? Oder sollte ich einfach die mypy Version verwenden?Wie überprüft man die Typkompatibilität bei Verwendung des Tippmoduls?

Bearbeiten: Hier ist ein Beispiel zu klären, was ich meine. Die DSL hat eine Funktion wie folgt definiert:

T = TypeVar('T', float, str) 
def op_add(operand1: T, operand2: T) -> T: 
    "Number addition or string concatenation." 
    # In this DSL, `+` cannot be used with lists 
    return operand1 + operand2 # Rely on Python overloading of `+` 

dann ein Benutzer in einem Ausdruck, der in einen Syntaxbaum analysiert wird, mit einem Zweig, der sein könnte: node = OperatorNode('+', Literal([5.0]), Variable("abc")). Wir kennen den Wert der Variablen abc noch nicht, aber Listen können niemals mit + verwendet werden. Daher möchte ich einen TypeError auslösen, um den Benutzer zu warnen.

Wenn ich issubclass(typing.List[float], var) mache, gibt mir das False, so kann ich sofort einen Fehler auslösen. Meine Frage ist, ob diese Kontrolle über Fälle arbeiten ist garantiert, wie ich den DSL bauen aus, oder wenn ich eine komplexere Kontrolle wie mypy

+0

Ich habe ein ABC verwendet und dann die Funktionen definiert, um das ABC und nicht die Unterklassen zu erwarten, und Mypy hat sich nie beschwert. Was genau sagt es für dich? –

Antwort

0

issubclass Prüfung verwenden müssen, ist ausreichend, wenn kein Argument zu issubclass Konstrukte aus typing Modul umfasst solche wie Union, Callable, Any, Generika, usw.

typing Konstrukte in python-Laufzeit als Schatten ihrer wahren Form vorliegen, ist, dass sie viele der Operationen, den Sinn nicht unterstützen konzeptionell machen:

issubclass(List[int], List[int]) # runtimem error 
issubclass(List[int], List) # True (as expected) 
issubclass(str, Union[str]) # runtime error 
issubclass(Union[str], str) # True (as expected) 
issubclass(Union[int, str], str) # runtime error 

Manchmal issubclass funktioniert mit typing Konstrukte, aber im Allgemeinen kann es eine Ausnahme auslösen oder eine falsche Antwort geben; Sie müssen von Fall zu Fall herausfinden, was zu tun ist.

mypy hat eine kompliziertere is_subtype, weil es alle typing Konstrukte zu handhaben muss, und selbst dann gibt es noch einige Arbeit dort getan werden.