Was macht dieses seltsame Doppelpunktverhalten?

103

Ich verwende Python 3.6.1 und bin auf etwas sehr Seltsames gestoßen. Ich hatte einen einfachen Tippfehler bei der Wörterbuchzuweisung, für dessen Suche ich lange gebraucht habe.

context = {}
context["a"]: 2
print(context)

Ausgabe

{}

Was macht der Code context["a"]: 2? Es wird nicht ausgelöst, SyntaxErrorwann es IMO sollte. Zuerst dachte ich, es würde eine Scheibe erzeugen. Durch Eingabe wird jedoch a repr(context["a"]: 2)ausgelöst SyntaxError. Ich habe auch context["a"]: 2die Konsole eingegeben und die Konsole hat nichts gedruckt. Ich dachte, vielleicht ist es zurückgekehrt None, aber ich bin mir nicht so sicher.

Ich habe auch gedacht, dass es eine einzelne Zeile if-Anweisung sein könnte, aber das sollte auch nicht die richtige Syntax sein.

Zusätzlich context["a"]sollte a KeyError.

Ich bin ratlos. Was ist los?

justengel
quelle
2
Diese Frage ist bereits betrogen und es ist ziemlich klar, dass dies für Python-Anfänger verwirrend ist. Ich denke, dies ist am schlimmsten, wenn Python Ihre einzige Sprache ist, in der sich Typhinweise und Variablendefinitionen vor der Initialisierung im Allgemeinen fremd anfühlen könnten. Ich stelle mir vor, dass es unmöglich ist, einen Fehler auszulösen, da dieses Verhalten absichtlich und manchmal nützlich ist, wie in PEP 526 erläutert, und Sie die Kompatibilität nicht beeinträchtigen möchten. Ich frage mich jedoch, ob die Python-Entwickler in einigen Fällen eine nützliche Warnmeldung hinzufügen würden.
Chris_Rands
1
Beantwortet das deine Frage? Was sind variable Annotationen in Python 3.6?
Georgy vor

Antworten:

97

Sie haben versehentlich eine syntaktisch korrekte Variablenanmerkung geschrieben . Diese Funktion wurde in Python 3.6 eingeführt (siehe PEP 526 ).

Obwohl eine variable Annotation als Teil einer annotierten Zuweisung analysiert wird , ist die Zuweisungsanweisung optional :

annotated_assignment_stmt ::=  augtarget ":" expression ["=" expression]

Also in context["a"]: 2

  • context["a"] ist das Anmerkungsziel
  • 2 ist die Anmerkung selbst
  • context["a"] wird nicht initialisiert

Das PEP gibt an, dass "das Ziel der Annotation zumindest syntaktisch ein beliebiges gültiges Einzelzuweisungsziel sein kann (es ist Sache der Typprüfung, was damit zu tun ist)" , was bedeutet, dass der Schlüssel nicht vorhanden sein muss kommentiert (daher nein KeyError). Hier ist ein Beispiel aus dem ursprünglichen PEP:

d = {}
d['a']: int = 0  # Annotates d['a'] with int.
d['b']: int      # Annotates d['b'] with int.

Normalerweise ist die Annotation Ausdruck sollte auf einen Python - Typen bewerten - schließlich die hauptsächliche Verwendung von Annotationen Type Hinting ist, aber es wird nicht erzwungen. Die Annotation kann ein beliebiger gültiger Python-Ausdruck sein, unabhängig vom Typ oder Wert des Ergebnisses.

Wie Sie sehen können, sind Typhinweise derzeit sehr freizügig und selten nützlich, es sei denn, Sie haben eine statische Typprüfung wie mypy .

Vaultah
quelle
12
Sollte dies =dann keinen Zuweisungsoperator erfordern ? Der Schlüssel existiert nicht. Das fühlt sich für mich einfach falsch an.
Justengel
1
In diesem Fall : ist der Zuweisungsoperator. Wir "weisen" nur eine Typanmerkung allein zu, keinen Schlüssel. Ich bezweifle, dass es einen Grund gibt, dies zuzulassen, nur einen unbeabsichtigten Nebeneffekt beim Hinzufügen der Anmerkungssyntax.
Chepner
1
@chepner Es scheint, dass dies keine Nebenwirkung imho ist. Genau dafür wurde der entsprechende PEP entwickelt.
Ma0
6
Es ist seltsam, dass Sie damit ein noch nicht definiertes Ziel mit Anmerkungen versehen können. Wenn meine allererste Zeile ist x: strund unmittelbar darauf folgt type(x), wird der Dolmetscher a auslösen NameError. IMO sollte die Syntax erzwingen, dass das Objekt vordefiniert oder vor Ort definiert ist. Dies führt nur zu Verwirrung.
r.ook
2
@Idlehands Dies macht den Zweck jedoch zunichte. Nachdem x = 'i am a string'vor x: strder letzteren Art überflüssig macht .. Dies sollte wurde überhaupt nicht gegeben. Es war gut als Kommentar; Ich zeige nie, dass es so oder so benutzt wird.
Ma0