Keine zurückgeben, wenn der Wörterbuchschlüssel nicht verfügbar ist

489

Ich brauche eine Möglichkeit, einen Wörterbuchwert zu erhalten, wenn sein Schlüssel vorhanden ist, oder einfach zurückzukehren None, wenn dies nicht der Fall ist.

Python löst jedoch eine KeyErrorAusnahme aus, wenn Sie nach einem Schlüssel suchen, der nicht vorhanden ist. Ich weiß, dass ich nach dem Schlüssel suchen kann, aber ich suche etwas expliziteres. Gibt es eine Möglichkeit, einfach zurückzukehren, Nonewenn der Schlüssel nicht vorhanden ist?

Spyros
quelle
74
Verwenden Sie einfach .get(key)anstelle von[key]
Gabe
12
Ein Dikt löst eine KeyError-Ausnahme aus. Key_error wird nicht zurückgegeben.
Ber
3
In Python ist es vollkommen in Ordnung, auf den Schlüssel zuzugreifen und die Ausnahme abzufangen. Es ist sogar ein bekanntes und häufig verwendetes Designmuster. Wenn Sie stattdessen None zurückgeben, ist es unmöglich, None als Wert zu speichern, was in einigen Fällen relevant sein kann.
Ber
1
Manchmal möchten Sie "Keine" Einträge im Wörterbuch und fehlende Einträge gleich behandeln. In diesem Fall scheint die akzeptierte Antwort den Job gut zu machen.
Cib
@Ber Ich habe die Frage bearbeitet, um zu klären. Das hättest du auch tun können.
Törzsmókus

Antworten:

813

Sie können verwenden dict.get()

value = d.get(key)

welches zurückkehren wird Nonewenn key is not in d. Sie können auch einen anderen Standardwert angeben, der zurückgegeben wird, anstatt None:

value = d.get(key, "empty")
Tim Pietzcker
quelle
47
Beachten Sie, dass die zweite Variante mit einem Standard-Fallback weiterhin zurückgegeben wird, Nonewenn der Schlüssel Noneim Diktat explizit zugeordnet ist . Wenn Sie das nicht möchten, können Sie so etwas verwenden d.get(key) or "empty".
Cib
15
@cib: Guter Punkt, aber die Lösung ein ähnliches Problem hat - wenn der Schlüssel zu einem „falsy“ Wert zugeordnet wird (wie [], "", False, 0.0oder in die Tat None), dann würde Ihre Lösung immer wieder zurückkehren 0. Wenn Sie Nones als Werte erwarten , müssen Sie die if key in d:Prüfung explizit durchführen.
Tim Pietzcker
1
@cib Prost dafür, ich konnte nicht herausfinden, was ich hier falsch gemacht habe.
Wobbily_col
@ TimPietzcker - kannst du bitte deine Antwort erklären? d.get (Schlüssel) oder "leer", wenn der Schlüssel einem "falschen" Wert zugeordnet ist, ist "leer", wenn ich mich nicht irre.
MiloMinderbinder
@MiloMinderbinder: "empty"wird zurückgegeben, wenn keykein gültiger Schlüssel eingegeben wurde d. Es hat nichts mit dem Wert zu tun, dem zugeordnet keyist.
Tim Pietzcker
63

Ich frage mich nicht mehr. Es ist in die Sprache eingebaut.

    >>> Hilfe (diktieren)

    Hilfe zum Klassendiktat in eingebauten Modulen:

    Klassendikt (Objekt)
     | dict () -> neues leeres Wörterbuch
     | dict (Zuordnung) -> Neues Wörterbuch, das von einem Zuordnungsobjekt initialisiert wurde
     | (Schlüssel, Wert) Paare
    ...
     |  
     | erhalten(...)
     | D.get (k [, d]) -> D [k] wenn k in D, sonst d. d ist standardmäßig None.
     |  
    ...
John La Rooy
quelle
22

Verwenden dict.get

Gibt den Wert für key zurück, wenn sich key im Wörterbuch befindet, andernfalls standardmäßig. Wenn kein Standardwert angegeben ist, wird standardmäßig None verwendet, sodass diese Methode niemals einen KeyError auslöst.

Daenyth
quelle
19

Sie sollten die get()Methode aus der dictKlasse verwenden

d = {}
r = d.get('missing_key', None)

Dies führt zu r == None. Wenn der Schlüssel nicht im Wörterbuch gefunden wird, gibt die Funktion get das zweite Argument zurück.

dusktreader
quelle
19
Sie müssen nicht Noneexplizit übergeben. Dies ist die Standardeinstellung.
Björn Pollex
18

Wenn Sie eine transparentere Lösung wünschen, können Sie eine Unterklasse erstellen dict, um dieses Verhalten zu erhalten:

class NoneDict(dict):
    def __getitem__(self, key):
        return dict.get(self, key)

>>> foo = NoneDict([(1,"asdf"), (2,"qwerty")])
>>> foo[1]
'asdf'
>>> foo[2]
'qwerty'
>>> foo[3] is None
True
Björn Pollex
quelle
2
@marineau: Wie ich in einem Kommentar zu einer anderen Antwort erwähnt habe, besteht das Problem defaultdictdarin, dass es jedes Mal wächst, wenn ein Element angefordert wird, das noch nicht vorhanden ist. Dies ist nicht immer wünschenswert.
Björn Pollex
@ BjörnPollex Dies ist bei weitem das elegante. Gibt es einen Hinweis darauf, wie man dies erweitern kann, um jede Tiefe zu unterstützen? Ich meine , dass foo['bar']['test']['sss']zurückzukehren Nonestatt Ausnahme, Nach einer Tiefe beginnen , es gibt TypeErrorstattKeyError
nehem
@itsneo. Sie könnten die gesamte Struktur von erstellen NoneDicts. Dies würde helfen, falls KeyErrordies im innersten Objekt passieren würde. Andernfalls besteht das Problem darin, dass Sie ein NoneObjekt nach der Rückgabe nicht mehr abonnieren können. Ein hässlicher Hack wäre, ein anderes Objekt zurückzugeben, das gerne testet None. Beachten Sie jedoch, dass dies zu schrecklichen Fehlern führen kann.
magu_
@ BjörnPollex Ist es in Ordnung zu ändern , return dict.get(self, key)zu return super().get(key)? Wenn ich mich dann zum Beispiel für OrderedDict anstelle von dict entscheide, muss ich mir keine Gedanken über das Ändern mehrerer Codezeilen machen.
Wood
@Wood Ja, das wäre eigentlich viel schöner!
Björn Pollex
12

Normalerweise verwende ich für solche Situationen ein Standarddiktat . Sie geben eine Factory-Methode an, die keine Argumente akzeptiert und einen Wert erstellt, wenn ein neuer Schlüssel angezeigt wird. Dies ist nützlicher, wenn Sie eine leere Liste mit neuen Schlüsseln zurückgeben möchten ( siehe Beispiele ).

from collections import defaultdict
d = defaultdict(lambda: None)
print d['new_key']  # prints 'None'
Job
quelle
19
Das Problem mit dem defaultdictist, dass es jedes Mal weiter wächst, wenn ein nicht vorhandenes Element angefordert wird.
Björn Pollex
8

Sie können dictdie get()Methode eines Objekts verwenden, wie andere bereits vorgeschlagen haben. Abhängig davon, was Sie gerade tun, können Sie möglicherweise eine try/exceptSuite wie die folgende verwenden:

try:
   <to do something with d[key]>
except KeyError:
   <deal with it not being there>

Dies wird als ein sehr "pythonischer" Ansatz zur Behandlung des Falls angesehen.

Martineau
quelle
7

Eine einzeilige Lösung wäre:

item['key'] if 'key' in item else None

Dies ist nützlich, wenn Sie versuchen, einer neuen Liste Wörterbuchwerte hinzuzufügen und eine Standardeinstellung angeben möchten:

z.B.

row = [item['key'] if 'key' in item else 'default_value']
imapotatoe123
quelle
5

Wie andere oben gesagt haben, können Sie get () verwenden.

Um nach einem Schlüssel zu suchen, können Sie jedoch auch Folgendes tun:

d = {}
if 'keyname' in d:

    # d['keyname'] exists
    pass

else:

    # d['keyname'] does not exist
    pass
Marek P.
quelle
Ich sehe jetzt, dass Sie bereits wissen, wie das geht. Ich wollte meinen Beitrag löschen, aber ich werde ihn anderen als Referenz überlassen.
Marek P
4
Bei diesem Ansatz muss der Schlüssel normalerweise zweimal nachgeschlagen werden, wenn er vorhanden ist. Dies ist wahrscheinlich der Grund für die getMethode.
Martineau
0

Ich war überrascht von dem, was in Python2 gegen Python3 möglich war. Ich werde es basierend auf dem beantworten, was ich letztendlich für Python3 getan habe. Mein Ziel war einfach: Überprüfen Sie, ob eine JSON-Antwort im Wörterbuchformat einen Fehler ergab oder nicht. Mein Wörterbuch heißt "Token" und mein gesuchter Schlüssel ist "Fehler". Ich suche nach dem Schlüssel "error" und wenn er nicht vorhanden war und auf den Wert None gesetzt wurde, wird überprüft, ob der Wert None ist. Wenn ja, fahren Sie mit meinem Code fort. Eine else-Anweisung würde behandelt, wenn ich den Schlüssel "error" habe.

if ((token.get('error', None)) is None):
    do something
FastGTR
quelle
-2

Wenn Sie es schaffen False, gibt es auch die in hasattr integrierte Funktion:

e=dict()
hasattr(e, 'message'):
>>> False
Evhz
quelle