Andere antwortet haben den Unterschied zwischen der Diktatklammertastung und der .get
y erwähnt eine Ziemlich unverfänglicher Fallstrick wenn None
oder der Standardwert ist ebenfalls ein gültiger Schlüssel.
Angesichts dieser Informationen könnte man zu dem Schluss kommen, dass .get
ist in gewisser Weise sicherer und besser als die Klammerindizierung und sollte immer anstelle von Klammernachschlagewerken verwendet werden, wie in Keine eckigen Klammern mehr verwenden, um den Wert eines Dictionarys in Python zu ermitteln selbst in dem üblichen Fall, in dem sie erwarten, dass die Suche erfolgreich ist (d. h., sie lösen niemals eine KeyError
).
Der Autor des Blogbeitrags argumentiert, dass .get
"schützt Ihren Code":
Beachten Sie, dass der Versuch, einen Begriff zu referenzieren, der nicht existiert, eine KeyError
. Dies kann zu erheblichen Problemen führen, insbesondere wenn es um unvorhersehbare Geschäftsdaten geht.
Wir könnten unsere Aussage zwar in eine try
/ except
o if
Aussage, so viel Sorgfalt für einen Wörterbuchbegriff wird sich schnell anhäufen.
Es stimmt, dass in dem seltenen Fall, dass null ( None
)-Koaleszenz oder anderweitiges Auffüllen eines fehlenden Wertes, um mit unvorhersehbaren dynamischen Daten umzugehen, ein mit Bedacht eingesetzter .get
ist ein nützliches und pythonisches Abkürzungswerkzeug für unhandliche if key in dct:
y try
/ except
Blöcke, die nur dazu da sind, Standardwerte zu setzen, wenn der Schlüssel als Teil der Verhaltensspezifikation für das Programm fehlen könnte.
Das Ersetzen von alle Klammern Sie diktierte Suchvorgänge, einschließlich derer, von denen Sie behaupten, dass sie erfolgreich sein müssen, mit .get
ist eine andere Sache. Diese Praxis degradiert eine Klasse von Laufzeitfehler die dazu beitragen, Fehler in stillen illegalen Zustandsszenarien aufzudecken, die in der Regel schwieriger zu identifizieren und zu debuggen sind.
Ein häufiger Fehler unter Programmierern ist es, Ausnahmen für verursachen Kopfschmerzen und versuchen, sie zu unterdrücken, indem sie Techniken wie die Einbettung von Code in try
... except: pass
Blöcke . Später erkennen sie die real Kopfzerbrechen bereitet der Bruch der Anwendungslogik an der Fehlerstelle und die Bereitstellung einer fehlerhaften Anwendung. Eine bessere Programmierpraxis ist die Verwendung von Assertions für alle Programminvarianten, z. B. für Schlüssel, die in einem Wörterbuch enthalten sein müssen.
Die Hierarchie der Fehlersicherheit lautet im Großen und Ganzen:
Fehler-Kategorie
Relativ einfaches Debugging
Fehler bei der Kompilierung
Ganz einfach: Gehen Sie zur Linie und beheben Sie das Problem.
Laufzeit-Ausnahme
Mittel; die Kontrolle muss zum Fehler fließen, und er kann auf unvorhergesehene Randfälle oder schwer zu reproduzierende Zustände wie eine Wettlaufbedingung zwischen Threads zurückzuführen sein, aber zumindest erhalten wir eine klare Fehlermeldung und einen Stack-Trace, wenn er auftritt.
Stiller logischer Fehler
Schwierig; wir wissen vielleicht nicht einmal, dass es ihn gibt, und wenn wir ihn doch finden, kann es sehr schwierig sein, den verursachenden Staat ausfindig zu machen, da er nicht lokalisierbar ist und möglicherweise mehrere Behauptungen verletzt.
Wenn die Entwickler von Programmiersprachen über Programmsicherheit sprechen, besteht ein Hauptziel darin, echte Fehler aufzudecken und nicht zu unterdrücken, indem Laufzeitfehler zu Kompilierzeitfehlern und stille logische Fehler entweder zu Laufzeitausnahmen oder (idealerweise) zu Kompilierzeitfehlern gemacht werden.
Python ist als interpretierte Sprache so konzipiert, dass es in hohem Maße auf Laufzeitausnahmen statt auf Compilerfehler angewiesen ist. Fehlende Methoden oder Eigenschaften, illegale Typoperationen wie 1 + "a"
und unzulässige oder fehlende Indizes oder Schlüssel werden standardmäßig ausgelöst.
Einige Sprachen wie JS, Java, Rust und Go verwenden standardmäßig das Fallback-Verhalten für ihre Maps (und bieten in vielen Fällen keine throw/raise-Alternative), aber Python wirft standardmäßig, zusammen mit anderen Sprachen wie C#. Perl/PHP geben eine Warnung bei nicht initialisierten Werten aus.
Willkürliche Anwendung von .get
für alle Diktatzugriffe, auch für solche, bei denen ein Fehlschlag nicht zu erwarten ist und die keine Ausweichmöglichkeit für den Umgang mit None
(oder welche Voreinstellung auch immer verwendet wird), die im Code Amok läuft, wirft so ziemlich Pythons Laufzeit-Ausnahme-Sicherheitsnetz für diese Klasse von Fehlern über den Haufen, indem es potenzielle Fehler zum Schweigen bringt oder ihnen eine Umleitung hinzufügt.
Weitere Gründe für die Bevorzugung von Klammersuchen (mit gelegentlichen, gut platzierten .get
wo ein Standardwert erwartet wird):
- Sie bevorzugen das Schreiben von standardmäßigem, idiomatischem Code unter Verwendung der von der Sprache bereitgestellten Werkzeuge. Python-Programmierer bevorzugen in der Regel (richtigerweise) Klammern aus den oben genannten Gründen der Ausnahmesicherheit und weil es das Standardverhalten für Python-Dicts ist.
- Immer mit
.get
die Absicht verwirkt, wenn Sie Fälle schaffen, in denen Sie eine Voreinstellung erwarten None
Wert, der nicht von einem Lookup zu unterscheiden ist, von dem Sie behaupten, dass er erfolgreich sein muss.
- Die Komplexität der Tests nimmt proportional zu den neuen "legalen" Programmpfaden zu, die durch
.get
. Beide Fälle müssen getestet werden, um die Abdeckung zu gewährleisten, selbst wenn der Standardpfad durch die Spezifikation effektiv unerreichbar ist (was ironischerweise zu zusätzlichen if val is not None:
o try
für alle zukünftigen Verwendungen des abgerufenen Wertes; unnötig und verwirrend für etwas, das nie sein sollte None
in erster Linie).
.get
ist ein bisschen langsamer .
.get
ist schwieriger zu tippen und hässlicher zu lesen (vergleiche Javas angeheftetes Gefühl ArrayList
Syntax zu nativem C# Lists
oder C++-Vektorcode). Unwichtig.
Einige Sprachen wie C++ und Ruby bieten alternative Methoden ( at
y fetch
), um bei einem fehlerhaften Zugriff einen Fehler auszulösen, während C# einen Opt-in-Fallback-Wert bietet TryGetValue
ähnlich wie bei Python get
.
Seit JS, Java, Ruby, Go und Rust backen den Fallback-Ansatz von .get
standardmäßig in alle Hash-Abfragen einbezieht, kann das doch nicht so schlimm sein, könnte man meinen. Es ist wahr, dass dies nicht das größte Problem ist, mit dem sich Sprachentwickler konfrontiert sehen, und es gibt viele Anwendungsfälle für die Version ohne Zugriffsmöglichkeit, daher ist es nicht überraschend, dass es keinen Konsens zwischen den Sprachen gibt.
Aber wie ich argumentiert habe, hat Python (zusammen mit C#) es besser gemacht als diese Sprachen, indem es die assert-Option zum Standard gemacht hat. Es ist ein Verlust an Sicherheit und Ausdruckskraft, wenn man die Option nicht verwendet, um Vertragsverletzungen am Punkt des Scheiterns zu melden, indem man wahllos .get
in allen Bereichen.