Warum dict.get (Schlüssel) anstelle von dict [Schlüssel]?

646

Heute bin ich auf die dictMethode getgestoßen, die bei einem Schlüssel im Wörterbuch den zugehörigen Wert zurückgibt.

Für welchen Zweck ist diese Funktion nützlich? Wenn ich einen Wert finden wollte, der einem Schlüssel in einem Wörterbuch zugeordnet ist, kann ich dies einfach tun dict[key], und es wird dasselbe zurückgegeben:

dictionary = {"Name": "Harry", "Age": 17}
dictionary["Name"]
dictionary.get("Name")
stensootla
quelle
1
dictionary["foo"]und dictionary.get("foo")verhalten sich jedoch anders.
Niklas B.
32
dictionary.get("Age") ist dasselbe wie das Schreiben, dictionary["Age"] or None daher wird die KeyError-Ausnahme implizit behandelt
yosemite_k
5
@yosemite_k Möglicherweise fehlt mir hier ein Kontext, aber ich dictionary['non-existent key'] or Nonesollte und muss trotzdem einen KeyErrorfür mich auslösen (bis v3.6). Können Sie erklären, was Sie meinen?
Nivk
@nivk dictionary ['nicht vorhandener Schlüssel'] löst einen Fehler aus, und dieser Fehler sollte explizit behandelt werden. Wenn Sie stattdessen dictionary.get () verwenden (das buchstäblich als Wörterbuch ['nicht vorhandener Schlüssel'] oder Keine fungiert), wird diese Ausnahme implizit behandelt.
yosemite_k

Antworten:

987

Sie können einen Standardwert angeben, wenn der Schlüssel fehlt:

dictionary.get("bogus", default_value)

gibt zurück default_value(was auch immer Sie wählen)

dictionary["bogus"]

würde ein erhöhen KeyError.

Wenn weggelassen, default_valueist None, so dass

dictionary.get("bogus")  # <-- No default specified -- defaults to None

kehrt Nonegenauso zurück wie

dictionary.get("bogus", None)

würde.

unutbu
quelle
1
Wäre das dasselbe wie dictionary.get("bogus") or my_default? Ich habe gesehen, wie Leute es in einigen Fällen benutzten, und ich habe mich gefragt, ob es einen Vorteil gibt, eines anstelle des anderen zu verwenden (außer Lesbarkeit)
Algorithmatic
15
@MustafaS: Wenn "bogus"ein Schlüssel eingegeben wird dictionaryund dictionary.get("bogus")ein Wert zurückgegeben wird, der in einem booleschen Kontext (dh einem Falsey-Wert) als False ausgewertet wird, z. B. 0 oder eine leere Zeichenfolge, ''wird dictionary.get("bogus") or my_defaultausgewertet, my_defaultwährend während dictionary.get("bogus", my_default)der Falsey-Wert zurückgegeben wird. Also nein, dictionary.get("bogus") or my_defaultist nicht gleichbedeutend mit dictionary.get("bogus", my_default). Welche Sie verwenden möchten, hängt vom gewünschten Verhalten ab.
Unutbu
3
@MustafaS: Nehmen wir zum Beispiel an x = {'a':0}. Dann x.get('a', 'foo')kehrt 0aber x.get('a') or 'foo'zurück 'foo'.
Unutbu
3
Eine mögliche Einschränkung bei der Verwendung dictionary.get('key'): Es kann verwirrend sein, ob Werte im Wörterbuch vorhanden sind None. Ohne Angabe des Rückgabewerts (zweites optionales Argument) kann nicht überprüft werden, ob der Schlüssel nicht vorhanden war oder ob sein Wert vorhanden ist None. In diesem speziellen Fall würde ich in Betracht ziehen, zu verwenden try-except-KeyError.
Aart Goossens
1
Es ist erwähnenswert, dass der Ausdruck zum Angeben des Standardwerts im Aufruf "get" ausgewertet wird und daher bei jedem Zugriff ausgewertet wird. Eine klassische Alternative (entweder mit einem KeyError-Handler oder einem Prädikat) besteht darin, den Standardwert nur dann auszuwerten, wenn der Schlüssel fehlt. Auf diese Weise kann ein Abschluss / Lambda einmal erstellt und für jeden fehlenden Schlüssel ausgewertet werden.
Tom Stambaugh
140

Was ist die dict.get()Methode?

Wie bereits erwähnt get, enthält die Methode einen zusätzlichen Parameter, der den fehlenden Wert angibt. Aus der Dokumentation

get(key[, default])

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

Ein Beispiel kann sein

>>> d = {1:2,2:3}
>>> d[1]
2
>>> d.get(1)
2
>>> d.get(3)
>>> repr(d.get(3))
'None'
>>> d.get(3,1)
1

Gibt es irgendwo Geschwindigkeitsverbesserungen?

Wie hier erwähnt ,

Es scheint, dass alle drei Ansätze jetzt eine ähnliche Leistung aufweisen (innerhalb von etwa 10% voneinander), mehr oder weniger unabhängig von den Eigenschaften der Wortliste.

Früher getwar es erheblich langsamer, jetzt ist die Geschwindigkeit jedoch fast vergleichbar, zusammen mit dem zusätzlichen Vorteil, den Standardwert zurückzugeben. Um alle unsere Abfragen zu löschen, können wir auf einer ziemlich großen Liste testen (Beachten Sie, dass der Test nur das Nachschlagen aller gültigen Schlüssel umfasst).

def getway(d):
    for i in range(100):
        s = d.get(i)

def lookup(d):
    for i in range(100):
        s = d[i]

Jetzt Timing dieser beiden Funktionen mit timeit

>>> import timeit
>>> print(timeit.timeit("getway({i:i for i in range(100)})","from __main__ import getway"))
20.2124660015
>>> print(timeit.timeit("lookup({i:i for i in range(100)})","from __main__ import lookup"))
16.16223979

Wie wir sehen können, ist die Suche schneller als die get, da es keine Funktionssuche gibt. Dies kann durchschaut werdendis

>>> def lookup(d,val):
...     return d[val]
... 
>>> def getway(d,val):
...     return d.get(val)
... 
>>> dis.dis(getway)
  2           0 LOAD_FAST                0 (d)
              3 LOAD_ATTR                0 (get)
              6 LOAD_FAST                1 (val)
              9 CALL_FUNCTION            1
             12 RETURN_VALUE        
>>> dis.dis(lookup)
  2           0 LOAD_FAST                0 (d)
              3 LOAD_FAST                1 (val)
              6 BINARY_SUBSCR       
              7 RETURN_VALUE  

Wo wird es nützlich sein?

Dies ist immer dann hilfreich, wenn Sie einen Standardwert angeben möchten, wenn Sie ein Wörterbuch nachschlagen. Dies reduziert sich

 if key in dic:
      val = dic[key]
 else:
      val = def_val

Zu einer einzelnen Zeile, val = dic.get(key,def_val)

Wo wird es NICHT nützlich sein?

Wann immer Sie eine KeyErrorErklärung zurückgeben möchten , dass der bestimmte Schlüssel nicht verfügbar ist. Die Rückgabe eines Standardwerts birgt auch das Risiko, dass ein bestimmter Standardwert ebenfalls ein Schlüssel sein kann!

Ist es möglich, getähnliche Funktionen zu haben dict['key']?

Ja! Wir müssen das __missing__in einer Diktat-Unterklasse implementieren .

Ein Beispielprogramm kann sein

class MyDict(dict):
    def __missing__(self, key):
        return None

Eine kleine Demonstration kann sein

>>> my_d = MyDict({1:2,2:3})
>>> my_d[1]
2
>>> my_d[3]
>>> repr(my_d[3])
'None'
Bhargav Rao
quelle
31
Goldstandard für StackOverflow-Antworten!
Apollo Data
1
Ein weiterer guter Test wäre if k in dict and dict[k]:vs if dict.get(k):. Dies deckt die Situation ab, in der überprüft werden muss, ob ein Schlüssel vorhanden ist, und wenn 'Ja' - welcher Wert?, So etwas wie : dict = {1: '', 2: 'some value'}.
TitanFighter
7
Bitte denken Sie daran , dass Standardwert wird unabhängig vom Wert Wesen im Wörterbuch ausgewertet, so dass anstelle von dictionary.get(value, long_function())einer Verwendung könnte prüfendictionary.get(value) or long_function()
Kresimir
Ah @Kresimir, stimmt. Ich habe diese Frage in einem der Interviews erhalten, mit denen ich konfrontiert war (ich wusste nichts davon, als ich diese Antwort ursprünglich gepostet hatte). Danke, dass du mich daran erinnert hast.
Bhargav Rao
31

getnimmt einen zweiten optionalen Wert an. Wenn der angegebene Schlüssel in Ihrem Wörterbuch nicht vorhanden ist, wird dieser Wert zurückgegeben.

dictionary = {"Name": "Harry", "Age": 17}
dictionary.get('Year', 'No available data')
>> 'No available data'

Wenn Sie den zweiten Parameter nicht angeben, Nonewird zurückgegeben.

Wenn Sie die Indizierung wie in verwenden dictionary['Year'], werden nicht vorhandene Schlüssel ausgelöst KeyError.

Gefallener Engel
quelle
19

Ich werde ein praktisches Beispiel für das Scraping von Webdaten mit Python geben. In vielen Fällen erhalten Sie Schlüssel ohne Werte. In diesen Fällen werden Fehler angezeigt, wenn Sie das Wörterbuch ['key'] verwenden, während dictionary.get ('key ',' return_otherwise ') hat keine Probleme.

Ebenso würde ich '' .join (Liste) im Gegensatz zu Liste [0] verwenden, wenn Sie versuchen, einen einzelnen Wert aus einer Liste zu erfassen.

ich hoffe es hilft.

[Bearbeiten] Hier ist ein praktisches Beispiel:

Angenommen, Sie rufen eine API auf, die eine JOSN-Datei zurückgibt, die Sie analysieren müssen. Der erste JSON sieht folgendermaßen aus:

{"bids":{"id":16210506,"submitdate":"2011-10-16 15:53:25","submitdate_f":"10\/16\/2011 at 21:53 CEST","submitdate_f2":"p\u0159ed 2 lety","submitdate_ts":1318794805,"users_id":"2674360","project_id":"1250499"}}

Der zweite JOSN ist wie folgt:

{"bids":{"id":16210506,"submitdate":"2011-10-16 15:53:25","submitdate_f":"10\/16\/2011 at 21:53 CEST","submitdate_f2":"p\u0159ed 2 lety","users_id":"2674360","project_id":"1250499"}}

Beachten Sie, dass dem zweiten JSON der Schlüssel "submitdate_ts" fehlt, was in jeder Datenstruktur ziemlich normal ist.

Wenn Sie also versuchen, in einer Schleife auf den Wert dieses Schlüssels zuzugreifen, können Sie ihn wie folgt aufrufen:

for item in API_call:
    submitdate_ts = item["bids"]["submitdate_ts"]

Sie könnten, aber es wird Ihnen einen Traceback-Fehler für die zweite JSON-Zeile geben, da der Schlüssel einfach nicht existiert.

Die geeignete Art, dies zu codieren, könnte die folgende sein:

for item in API_call:
    submitdate_ts = item.get("bids", {'x': None}).get("submitdate_ts")

{'x': Keine} ist vorhanden, um zu vermeiden, dass die zweite Ebene einen Fehler erhält. Natürlich können Sie beim Scraping mehr Fehlertoleranz in den Code einbauen. Wie zuerst eine if-Bedingung angeben

Kevin
quelle
2
Eine gute Antwort, die vor allen anderen veröffentlicht wurde, die mehr positiv bewertet und wahrscheinlich akzeptiert worden wäre, wenn Sie einige Codebeispiele veröffentlicht hätten (allerdings +1 von mir)
Mawg sagt, Monica am
2
@Mawg Ich hatte kürzlich ein Scraping-Projekt für meine Forschung. Grundsätzlich wurde eine API aufgerufen und JSON-Dateien analysiert. Ich ließ es von meiner RA machen. Eines der Hauptprobleme war das direkte Aufrufen des Schlüssels, wenn tatsächlich viele Schlüssel fehlen. Ich werde ein Beispiel im obigen Text veröffentlichen.
Kevin
Vielen Dank, dass Sie sich mit dem mehrdimensionalen Aspekt befasst haben! Klingt so, als könnten Sie sogar {} anstelle von {'x': Keine}
tun
17

Der Zweck ist, dass Sie einen Standardwert angeben können, wenn der Schlüssel nicht gefunden wird, was sehr nützlich ist

dictionary.get("Name",'harry')
Hackartist
quelle
8

Für welchen Zweck ist diese Funktion nützlich?

Eine besondere Verwendung ist das Zählen mit einem Wörterbuch. Angenommen, Sie möchten die Anzahl der Vorkommen jedes Elements in einer bestimmten Liste zählen. Der übliche Weg, dies zu tun, besteht darin, ein Wörterbuch zu erstellen, in dem Schlüssel Elemente und Werte die Anzahl der Vorkommen sind.

fruits = ['apple', 'banana', 'peach', 'apple', 'pear']
d = {}
for fruit in fruits:
    if fruit not in d:
        d[fruit] = 0
    d[fruit] += 1

Mit der .get()Methode können Sie diesen Code kompakter und klarer gestalten:

for fruit in fruits:
    d[fruit] = d.get(fruit, 0) + 1
jetpack_guy
quelle
7

Ein Gotcha, das Sie beachten sollten, wenn Sie Folgendes verwenden .get():

Wenn das Wörterbuch den im Aufruf von verwendeten Schlüssel enthält .get()und dessen Wert lautet None, gibt die .get()Methode auch dann zurück None, wenn ein Standardwert angegeben wird.

Die folgenden Ergebnisse Nonewerden beispielsweise nicht 'alt_value'wie erwartet zurückgegeben:

d = {'key': None}
d.get('key', 'alt_value')

.get()Der zweite Wert wird nur zurückgegeben, wenn sich der angegebene Schlüssel NICHT im Wörterbuch befindet, nicht wenn der Rückgabewert dieses Aufrufs lautet None.

Colton Hicks
quelle
1
Dieser hat mich dazu gebracht: \ Ein Weg, dies zu lösen, ist zu haben, d.get('key') or 'alt_value'wenn Sie wissen, dass es sein könnteNone
Daniel Holmes
4

Warum dict.get (Schlüssel) anstelle von dict [Schlüssel]?

0. Zusammenfassung

Im Vergleich zu dict[key], dict.getstellt einen Fehlerwert , wenn für einen Schlüssel aufzuzublicken.

1. Definition

get (key [, default]) 4. Integrierte Typen - Python 3.6.4rc1-Dokumentation

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.

d = {"Name": "Harry", "Age": 17}
In [4]: d['gender']
KeyError: 'gender'
In [5]: d.get('gender', 'Not specified, please add it')
Out[5]: 'Not specified, please add it'

2. Problem, das es löst.

Wenn nicht default value, müssen Sie umständliche Codes schreiben, um eine solche Ausnahme zu behandeln.

def get_harry_info(key):
    try:
        return "{}".format(d[key])
    except KeyError:
        return 'Not specified, please add it'
In [9]: get_harry_info('Name')
Out[9]: 'Harry'
In [10]: get_harry_info('Gender')
Out[10]: 'Not specified, please add it'

dict.getFührt als bequeme Lösung einen optionalen Standardwert ein, der die oben genannten ungewollten Codes vermeidet.

3. Fazit

dict.get verfügt über eine zusätzliche Standardwertoption zur Behandlung von Ausnahmen, wenn der Schlüssel im Wörterbuch nicht vorhanden ist

Infinitesimalrechnung
quelle
0

Ein Unterschied, der von Vorteil sein kann, besteht darin, dass wir, wenn wir nach einem Schlüssel suchen, der nicht existiert, None erhalten, nicht wie bei Verwendung der Klammernotation. In diesem Fall wird ein Fehler ausgegeben:

print(dictionary.get("address")) # None
print(dictionary["address"]) # throws KeyError: 'address'

Das Letzte, was an der get-Methode cool ist, ist, dass sie ein zusätzliches optionales Argument für einen Standardwert erhält, dh wenn wir versucht haben, den Bewertungswert eines Schülers abzurufen, der Schüler jedoch keinen Bewertungsschlüssel hat, den wir abrufen können stattdessen eine 0.

Also anstatt dies zu tun (oder etwas Ähnliches):

score = None
try:
    score = dictionary["score"]
except KeyError:
    score = 0

Wir können das schaffen:

score = dictionary.get("score", 0)
# score = 0
אנונימי
quelle
-1

Basierend auf der Verwendung sollte diese getMethode verwendet werden.

Beispiel 1

In [14]: user_dict = {'type': False}

In [15]: user_dict.get('type', '')

Out[15]: False

In [16]: user_dict.get('type') or ''

Out[16]: ''

Beispiel2

In [17]: user_dict = {'type': "lead"}

In [18]: user_dict.get('type') or ''

Out[18]: 'lead'

In [19]: user_dict.get('type', '')

Out[19]: 'lead'
Muthuvel
quelle