Unterschied zwischen der Definition der Eingabe. Diktat und Diktat?

102

Ich übe die Verwendung von Typhinweisen in Python 3.5. Einer meiner Kollegen verwendet typing.Dict:

import typing


def change_bandwidths(new_bandwidths: typing.Dict,
                      user_id: int,
                      user_name: str) -> bool:
    print(new_bandwidths, user_id, user_name)
    return False


def my_change_bandwidths(new_bandwidths: dict,
                         user_id: int,
                         user_name: str) ->bool:
    print(new_bandwidths, user_id, user_name)
    return True


def main():
    my_id, my_name = 23, "Tiras"
    simple_dict = {"Hello": "Moon"}
    change_bandwidths(simple_dict, my_id, my_name)
    new_dict = {"new": "energy source"}
    my_change_bandwidths(new_dict, my_id, my_name)

if __name__ == "__main__":
    main()

Beide funktionieren einwandfrei, es scheint keinen Unterschied zu geben.

Ich habe die typingModuldokumentation gelesen .

Zwischen typing.Dictoder dictwelche soll ich im Programm verwenden?

Sarit
quelle
11
Beachten Sie, dass Python keine Typhinweise erzwingt . Sie sind nur Hinweise , sie werden nicht zur Laufzeit oder gar zur Kompilierungszeit verwendet, um Typen durchzusetzen. Python kann stark typisiert sein (Gegenteil von schwacher Typisierung), es wird auch dynamisch typisiert (Gegenteil von strikter Typisierung). Siehe Ist Python stark typisiert? . Externe Tools wie mypy können diese Hinweise verwenden, um Ihnen zu helfen, besseren Code in einem Prozess zu schreiben, der als statische Analyse bezeichnet wird.
Martijn Pieters
1
@MartijnPieters Ich habe es geliebt, neben MyPy Typhinweise in meinem Code zu verwenden und so zu tun, als könnte ich Python mit Typensicherheit verwenden. Leider habe ich A) Code bekommen, der bei <3.4 nicht funktioniert, und B) Leute, die mich auslachen, weil Typhinweise anscheinend ein Gespött sind. Es ist wirklich ziemlich unglücklich.
Katze
3
@cat: Typhinweise wurden von einem Facebook-Mitarbeiter in Python eingeführt, da wir enormen Erfolg damit hatten, PHP dieselbe Funktion hinzuzufügen (siehe Hack ). Wer lacht, hat noch nie ein großes Projekt mit mehr als einer Handvoll Ingenieuren aufgebaut.
Martijn Pieters
3
@MartijnPieters Nein, def a(b: int) -> bool:ist ein Syntaxfehler in Python 2.7, und ich denke, es ist auch ein Syntaxfehler in älteren Versionen von Python 3.
Katze
1
@cat: Sie sprechen hier von Funktionsanmerkungen , einer Syntax, die Python 3.0 hinzugefügt wurde. Die einzige Version, bei der dies ein Syntaxfehler ist, ist 2.7, weshalb mypy das Einfügen dieser Informationen in Kommentare unterstützt.
Martijn Pieters

Antworten:

139

Es gibt keinen wirklichen Unterschied zwischen der Verwendung einer Ebene typing.Dictund dict, nein.

Allerdings typing.Dictist eine generische Art , die Sie angeben , die Art des Schlüssels und Werte kann auch , um sie flexibler zu machen:

def change_bandwidths(new_bandwidths: typing.Dict[str, str],
                      user_id: int,
                      user_name: str) -> bool:

Daher kann es durchaus sein, dass Sie zu einem bestimmten Zeitpunkt in Ihrer Projektlaufzeit das Wörterbuchargument etwas genauer definieren möchten. Zu diesem Zeitpunkt ist das Erweitern typing.Dictauf typing.Dict[key_type, value_type]eine „kleinere“ Änderung als das Ersetzen dict.

Sie können dies noch allgemeiner gestalten, indem Sie hier Mappingoder MutableMappingeingeben. Da Ihre Funktion das Mapping nicht ändern muss, bleibe ich dabei Mapping. A dictist eine Zuordnung, aber Sie können auch andere Objekte erstellen, die auch die Zuordnungsschnittstelle erfüllen, und Ihre Funktion funktioniert möglicherweise weiterhin mit diesen:

def change_bandwidths(new_bandwidths: typing.Mapping[str, str],
                      user_id: int,
                      user_name: str) -> bool:

Jetzt teilen Sie anderen Benutzern dieser Funktion klar mit, dass Ihr Code die übergebene Zuordnung nicht wirklich ändertnew_bandwidths .

Ihre eigentliche Implementierung erwartet lediglich ein druckbares Objekt. Das mag eine Testimplementierung sein, aber so wie es aussieht, würde Ihr Code weiterhin funktionieren, wenn Sie ihn verwenden new_bandwidths: typing.Any, da jedes Objekt in Python druckbar ist.

Martijn Pieters
quelle
2
Nützliche zusätzliche Beispiele wären, wenn die Wörterbuchwerte unterschiedliche Typen haben können, z. B. {"name": "bob", "age" : 51}wäre das so etwas wie typing.Mapping[Union[str, int]? Was ist mit einem verschachtelten Wörterbuch wie {"person": {"name":"bob", "age": 51}wäre das wie etwas sein typing.Mapping[str, typing.Mapping[Union[str, int]]? Die Verwendung Uniondieser Funktion stört mich, da es sich nicht um ein striktes Schema handelt, da keine Reihenfolge vorliegt. Vielleicht ist das in Ordnung oder gibt es eine Alternative?
Davos
1
Vergiss die UnionFrage, die ich sehe, es ist immer noch eine offene Diskussion. Github.com/python/typing/issues/28
Davos
1
Dies scheint sehr interessant, nützlich und verwandt zu sein python.org/dev/peps/pep-0589
Greg Hilston
@ GregHilston: Hier geht es eigentlich darum, wie Sie einschränken können, welche Schlüssel ein Wörterbuch enthalten kann, und angeben, welche Typen jeder zugeordnete Wert haben soll.
Martijn Pieters
1
@ GregHilston: Ah, ja, das ist es.
Martijn Pieters
26

typing.Dictist eine generische Version von dict:

class typing.Dict(dict, MutableMapping[KT, VT])

Eine generische Version von dict. Die Verwendung dieses Typs ist wie folgt:

def get_position_in_index(word_list: Dict[str, int], word: str) -> int:
     return word_list[word]

Hier können Sie den Schlüsseltyp und die Werte im Diktat angeben: Dict[str, int]

AKS
quelle