Restituisce Nessuno se la chiave del dizionario non è disponibile


490

Ho bisogno di un modo per ottenere un valore di dizionario se esiste la sua chiave, o semplicemente restituire None, se non lo fa.

Tuttavia, Python solleva KeyErrorun'eccezione se cerchi una chiave che non esiste. So che posso verificare la chiave, ma sto cercando qualcosa di più esplicito. C'è un modo per tornare Nonese la chiave non esiste?


74
Basta usare .get(key)invece di[key]
Gabe

12
Un dict solleva un'eccezione KeyError. Non "restituisce key_error".
Ber,

3
Accedere alla chiave e catturare l'eccezione è perfettamente ok in Python. È anche un modello di design ben noto e spesso usato. Se si restituisce None, diventa impossibile archiviare None come valore, che può essere rilevante in alcuni casi.
Ber,

1
A volte si desidera trattare le voci "Nessuna" nel dizionario e le voci mancanti uguali, in tal caso la risposta accettata sembra fare il lavoro bene.
cib

@Ber Ho modificato la domanda per chiarire. Avresti potuto farlo anche tu.
törzsmókus,

Risposte:


814

Puoi usare dict.get()

value = d.get(key)

che restituirà Nonese key is not in d. È inoltre possibile fornire un valore predefinito diverso che verrà restituito anziché None:

value = d.get(key, "empty")

47
Si noti che la seconda variante con un fallback predefinito tornerà comunque Nonese la chiave è esplicitamente mappata Nonenel dict. Se non è quello che vuoi, puoi usare qualcosa del genere d.get(key) or "empty".
cib

15
@cib: Buon punto, ma la soluzione ha un problema simile - se la chiave è mappata a qualsiasi valore "falsy" (come [], "", False, 0.0o addirittura None), allora la soluzione sarebbe sempre ritornare 0. Se ti aspetti Nonecome valori, dovrai fare il if key in d:controllo esplicitamente.
Tim Pietzcker,

1
@cib esulta per questo, non sono riuscito a capire cosa stavo facendo di sbagliato qui.
wobbily_col,

@TimPietzcker - puoi per favore spiegare la tua risposta? d.get (chiave) o "vuoto" nel caso in cui la chiave venga mappata su valori 'falsi' è "vuoto" se non sbaglio.
MiloMinderbinder

@MiloMinderbinder: "empty"viene restituito se keynon è una chiave valida d. Non ha nulla a che fare con il valore su cui keyè mappato.
Tim Pietzcker,

63

Non mi chiedo più. È incorporato nella lingua.

    >>> aiuto (dict)

    Aiuto su class dict nei moduli integrati:

    class dict (oggetto)
     | dict () -> nuovo dizionario vuoto
     | dict (mapping) -> nuovo dizionario inizializzato da un oggetto mapping
     | (chiave, valore) coppie
    ...
     |  
     | ottenere(...)
     | D.get (k [, d]) -> D [k] se k in D, altrimenti d. d il valore predefinito è Nessuno.
     |  
    ...

22

Uso dict.get

Restituisce il valore per chiave se chiave è nel dizionario, altrimenti impostazione predefinita. Se non viene fornito il valore predefinito, il valore predefinito è Nessuno, quindi questo metodo non genera mai un KeyError.


19

Dovresti usare il get()metodo della dictclasse

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

Ciò comporterà r == None. Se la chiave non viene trovata nel dizionario, la funzione get restituisce il secondo argomento.


19
Non devi passare Noneesplicitamente. È l'impostazione predefinita
Björn Pollex,

18

Se si desidera una soluzione più trasparente, è possibile eseguire la sottoclasse dictper ottenere questo comportamento:

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

2
@marineau: Come ho già detto in un commento a un'altra risposta, il problema defaultdictè che crescerà ogni volta che viene richiesto un elemento che non è ancora presente. Questo non è sempre desiderabile.
Björn Pollex,

@ BjörnPollex Questo è di gran lunga quello elegante, Qualche idea su come estenderlo per supportare qualsiasi profondità? Intendo far foo['bar']['test']['sss']tornare Noneinvece che un'eccezione, dopo una profondità inizia a dare TypeErrorinvece diKeyError
nehem

@itsneo. Potresti costruire l'intera struttura di NoneDicts. Ciò aiuterebbe nel caso in cui KeyErrorciò accadesse nell'oggetto più interno. Altrimenti il ​​problema è che una volta restituito un Noneoggetto non è più possibile iscriverlo. Un brutto trucco sarebbe quello di restituire un altro oggetto che prova come None. Attenzione però che questo potrebbe portare a orribili bug.
magu_

@ BjörnPollex Va bene cambiare return dict.get(self, key)a return super().get(key)? Quindi, se decido di utilizzare OrderedDict anziché dict, ad esempio, non devo preoccuparmi di modificare più righe di codice.
Legno,

@Wood Sì, sarebbe davvero molto più bello!
Björn Pollex,

12

Di solito uso un valore predefinito per situazioni come questa. Fornisci un metodo factory che non accetta argomenti e crea un valore quando vede una nuova chiave. È più utile quando si desidera restituire qualcosa come un elenco vuoto su nuove chiavi ( vedere gli esempi ).

from collections import defaultdict
d = defaultdict(lambda: None)
print d['new_key']  # prints 'None'

19
Il problema defaultdictè che continuerà a crescere ogni volta che viene richiesto un elemento inesistente.
Björn Pollex,

8

È possibile utilizzare dictil get()metodo di un oggetto , come altri hanno già suggerito. In alternativa, a seconda di cosa stai facendo, potresti essere in grado di utilizzare una try/exceptsuite come questa:

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

Che è considerato un approccio molto "Pythonic" alla gestione del caso.


7

Una soluzione a una riga sarebbe:

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

Ciò è utile quando si tenta di aggiungere valori di dizionario a un nuovo elenco e si desidera fornire un valore predefinito:

per esempio.

row = [item['key'] if 'key' in item else 'default_value']

5

Come altri hanno già detto sopra, puoi usare get ().

Ma per cercare una chiave, puoi anche fare:

d = {}
if 'keyname' in d:

    # d['keyname'] exists
    pass

else:

    # d['keyname'] does not exist
    pass

Ora vedo che sai già come farlo. Stavo per eliminare il mio post, ma lo lascerò come riferimento per gli altri.
Marek P,

4
Questo approccio di solito richiede che la chiave venga cercata due volte quando è lì, che è probabilmente la ragione del getmetodo.
martineau,

0

Sono stato sorpreso da ciò che era possibile in python2 vs python3. Risponderò in base a ciò che ho finito per fare per python3. Il mio obiettivo era semplice: verificare se una risposta json in formato dizionario ha dato un errore o meno. Il mio dizionario si chiama "token" e la mia chiave che sto cercando è "errore". Sto cercando la chiave "errore" e se non era lì impostandolo sul valore di Nessuno, quindi il controllo è il valore è Nessuno, se così procedere con il mio codice. Un'istruzione else gestirebbe se avessi la chiave "errore".

if ((token.get('error', None)) is None):
    do something

-2

Se riesci a farlo False, allora c'è anche la funzione integrata hasattr :

e=dict()
hasattr(e, 'message'):
>>> False
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.