Waarom dict.get(key) in plaats van dict[key]?

Vandaag kwam ik de dict-methode gettegen die, gegeven een sleutel in het woordenboek, de bijbehorende waarde retourneert.

Waarvoor is deze functie nuttig? Als ik een waarde wil vinden die is gekoppeld aan een sleutel in een woordenboek, kan ik gewoon dict[key]doen, en het geeft hetzelfde terug:

dictionary = {"Name": "Harry", "Age": 17}
dictionary["Name"]
dictionary.get("Name")

Antwoord 1, autoriteit 100%

Hiermee kunt u een standaardwaarde opgeven als de sleutel ontbreekt:

dictionary.get("bogus", default_value)

retourneert default_value(wat je ook kiest), terwijl

dictionary["bogus"]

zou een KeyErrorveroorzaken.

Indien weggelaten, is default_valueNone, zodat

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

retourneert Nonenet als

dictionary.get("bogus", None)

zou.


Antwoord 2, autoriteit 15%

Wat is de dict.get()methode?

Zoals reeds vermeld bevat de getmethode een extra parameter die de ontbrekende waarde aangeeft. Uit de documentatie

get(key[, default])

Retourneer de waarde voor sleutel als sleutel in het woordenboek staat, anders standaard. Als standaard niet is opgegeven, wordt deze standaard ingesteld op Geen, zodat deze methode nooit een KeyErroroplevert.

Een voorbeeld kan zijn

>>> 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

Zijn er ergens snelheidsverbeteringen?

Zoals vermeld hier,

Het lijkt erop dat alle drie de benaderingen nu vergelijkbare prestaties vertonen (binnen ongeveer 10% van elkaar), min of meer onafhankelijk van de eigenschappen van de woordenlijst.

Eerder was getaanzienlijk langzamer, maar nu is de snelheid bijna vergelijkbaar, samen met het extra voordeel van het retourneren van de standaardwaarde. Maar om al onze vragen te wissen, kunnen we testen op een vrij grote lijst (merk op dat de test alleen het opzoeken van alle geldige sleutels omvat)

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

Tim nu deze twee functies met behulp van 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

Zoals we kunnen zien is de lookup sneller dan de get, omdat er geen functie-lookup is. Dit is te zien via dis

>>> 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  

Waar is het nuttig?

Het is handig wanneer u een standaardwaarde wilt opgeven wanneer u een woordenboek zoekt. Dit vermindert

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

Naar een enkele regel, val = dic.get(key,def_val)

Waar is het NIET nuttig?

Telkens wanneer u een KeyErrorwilt retourneren waarin staat dat de specifieke sleutel niet beschikbaar is. Het retourneren van een standaardwaarde brengt ook het risico met zich mee dat een bepaalde standaardwaarde ook een sleutel kan zijn!

Is het mogelijk om een getlike-functie in dict['key']te hebben?

Ja! We moeten de __missing__implementeren in een dict-subklasse.

Een voorbeeldprogramma kan zijn

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

Een kleine demonstratie kan zijn

>>> my_d = MyDict({1:2,2:3})
>>> my_d[1]
2
>>> my_d[3]
>>> repr(my_d[3])
'None'

Antwoord 3, autoriteit 3%

getheeft een tweede optionele waarde. Als de opgegeven sleutel niet in uw woordenboek voorkomt, wordt deze waarde geretourneerd.

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

Als u de tweede parameter niet opgeeft, wordt Nonegeretourneerd.

Als u indexering gebruikt zoals in dictionary['Year'], zullen niet-bestaande sleutels KeyErrorverhogen.


Antwoord 4, autoriteit 2%

Ik zal een praktisch voorbeeld geven van het schrapen van webgegevens met python, vaak krijg je sleutels zonder waarden, in die gevallen krijg je fouten als je dictionary [‘key’] gebruikt, terwijl dictionary.get (‘key’, ‘return_otherwise’) heeft geen problemen.

Op dezelfde manier zou ik ”.join(list) gebruiken in plaats van list[0] als je een enkele waarde uit een lijst probeert te halen.

hoop dat het helpt.

[Bewerken] Hier is een praktisch voorbeeld:

Stel, u roept een API aan, die een JOSN-bestand retourneert dat u moet ontleden. De eerste JSON ziet er als volgt uit:

{"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"}}

De tweede JOSN is als volgt:

{"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"}}

Merk op dat de tweede JSON de sleutel “submitdate_ts” mist, wat vrij normaal is in elke gegevensstructuur.

Dus wanneer u probeert toegang te krijgen tot de waarde van die sleutel in een lus, kunt u deze dan als volgt aanroepen:

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

Dat zou kunnen, maar dan krijg je een traceback-fout voor de tweede JSON-regel, omdat de sleutel gewoon niet bestaat.

De juiste manier om dit te coderen kan de volgende zijn:

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

{‘x’: Geen} is er om te voorkomen dat het tweede niveau een fout krijgt. Natuurlijk kunt u meer fouttolerantie in de code inbouwen als u aan het scrapen bent. Zoals eerst een if-voorwaarde specificeren


Antwoord 5, autoriteit 2%

Het doel is dat je een standaardwaarde kunt geven als de sleutel niet wordt gevonden, wat erg handig is

dictionary.get("Name",'harry')

Antwoord 6

Een probleem om op te letten bij het gebruik van .get():

Als het woordenboek de sleutel bevat die wordt gebruikt in de aanroep van .get()en de waarde ervan Noneis, wordt de .get()methode retourneert Nonezelfs als er een standaardwaarde is opgegeven.

Bijvoorbeeld, het volgende retourneert None, niet 'alt_value'zoals verwacht mag worden:

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

De tweede waarde van

.get()wordt alleen geretourneerd als de opgegeven sleutel NIET in het woordenboek staat, niet als de geretourneerde waarde van die aanroep Noneis.


Antwoord 7

Waarvoor is deze functie nuttig?

Een bepaald gebruik is tellen met een woordenboek. Laten we aannemen dat u het aantal keren dat elk element in een bepaalde lijst voorkomt, wilt tellen. De gebruikelijke manier om dit te doen is door een woordenboek te maken waarin sleutels elementen zijn en waarden het aantal keren dat ze voorkomen.

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

Met de .get()methode kun je deze code compacter en duidelijker maken:

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

Antwoord 8

Waarom dict.get(key) in plaats van dict[key]?

0. Samenvatting

Vergeleken met dict[key]biedt dict.geteen terugvalwaarde bij het zoeken naar een sleutel.

1. Definitie

get(key[, default]) 4. Ingebouwde typen — Python 3.6.4rc1-documentatie

Retourneer de waarde voor sleutel als sleutel in het woordenboek staat, anders standaard. Als standaard niet is opgegeven, wordt deze standaard ingesteld op Geen, zodat deze methode nooit een KeyError oplevert.

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. Probleem dat het oplost.

Als je geen default valuehebt, moet je omslachtige codes schrijven om een dergelijke uitzondering af te handelen.

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'

Als handige oplossing introduceert dict.geteen optionele standaardwaarde die bovenstaande onwettige codes vermijdt.

3. Conclusie

dict.getheeft een extra standaardwaarde-optie om met uitzonderingen om te gaan als de sleutel afwezig is in het woordenboek


Antwoord 9

Een verschil, dat een voordeel kan zijn, is dat als we op zoek zijn naar een sleutel die niet bestaat, we Geen krijgen, niet zoals wanneer we de haakjesnotatie gebruiken, in welk geval we een foutmelding krijgen:

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

Het laatste dat cool is aan de get-methode, is dat deze een extra optioneel argument voor een standaardwaarde ontvangt, dat wil zeggen als we probeerden de scorewaarde van een student te krijgen, maar de student heeft geen scoresleutel we kunnen in plaats daarvan een 0 krijgen.

Dus in plaats van dit (of iets dergelijks) te doen:

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

We kunnen dit doen:

score = dictionary.get("score", 0)
# score = 0

Antwoord 10

Een andere use-case die ik niet genoemd zie, is het argument keyvoor functies zoals sorted, maxen min. Met de get-methode kunnen sleutels worden geretourneerd op basis van hun waarden.

>>> ages = {"Harry": 17, "Lucy": 16, "Charlie": 18}
>>> print(sorted(ages, key=ages.get))
['Lucy', 'Harry', 'Charlie']
>>> print(max(ages, key=ages.get))
Charlie
>>> print(min(ages, key=ages.get))
Lucy

Dankzij dit antwoordop een andere vraag voor het verstrekken van deze use-case!


Antwoord 11

Op basis van gebruik moet deze get-methode worden gebruikt.

Voorbeeld1

In [14]: user_dict = {'type': False}
In [15]: user_dict.get('type', '')
Out[15]: False
In [16]: user_dict.get('type') or ''
Out[16]: ''

Voorbeeld2

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'

Other episodes