Kembali Tidak Ada jika kunci Kamus tidak tersedia

490

Saya perlu cara untuk mendapatkan nilai kamus jika kuncinya ada, atau cukup kembali None, jika tidak.

Namun, Python memunculkan KeyErrorpengecualian jika Anda mencari kunci yang tidak ada. Saya tahu bahwa saya dapat memeriksa kuncinya, tetapi saya mencari sesuatu yang lebih eksplisit. Apakah ada cara untuk kembali Nonejika kuncinya tidak ada?

Spyros
sumber
74
Cukup gunakan .get(key)sebagai gantinya[key]
Gabe
12
Diktat memunculkan pengecualian KeyError. Itu tidak "mengembalikan key_error".
Ber
3
Mengakses kunci dan menangkap pengecualian benar-benar oke dengan Python. Ini bahkan merupakan pola desain yang terkenal dan sering digunakan. Jika Anda mengembalikan Tidak ada, menjadi tidak mungkin untuk menyimpan Tidak ada sebagai nilai, yang mungkin relevan dalam beberapa kasus.
Ber
1
Terkadang Anda ingin memperlakukan entri "Tidak Ada" di kamus dan entri yang hilang sama, dalam hal itu jawaban yang diterima tampaknya melakukan pekerjaan dengan baik.
cib
@ Sebelumnya saya telah mengedit pertanyaan untuk menjelaskan. Anda bisa melakukannya juga.
törzsmókus

Jawaban:

814

Kamu bisa menggunakan dict.get()

value = d.get(key)

yang akan kembali Nonejika key is not in d. Anda juga dapat memberikan nilai default berbeda yang akan dikembalikan alih-alih None:

value = d.get(key, "empty")
Tim Pietzcker
sumber
47
Perhatikan bahwa varian kedua dengan fallback default masih akan kembali Nonejika kunci secara eksplisit dipetakan ke Nonedalam dict. Jika bukan itu yang Anda inginkan, Anda dapat menggunakan sesuatu seperti d.get(key) or "empty".
cib
15
@cib: Bagus, tetapi solusi memiliki masalah yang sama - jika kunci dipetakan ke nilai "falsy" (seperti [], "", False, 0.0atau memang None), maka solusinya Anda akan selalu kembali 0. Jika Anda mengharapkan Nones sebagai nilai, Anda harus melakukan if key in d:pemeriksaan secara eksplisit.
Tim Pietzcker
1
@cib bersorak untuk itu, saya tidak bisa menemukan kesalahan saya di sini.
wobbily_col
@TimPietzcker - bisakah Anda menjelaskan jawaban Anda? d.get (kunci) atau "kosong" jika kunci dipetakan ke nilai 'palsu' adalah "kosong" jika saya tidak salah.
MiloMinderbinder
@MiloMinderbinder: "empty"dikembalikan jika keybukan kunci yang valid d. Ini tidak ada hubungannya dengan nilai keyyang dipetakan.
Tim Pietzcker
63

Bertanya-tanya lagi. Itu dibangun ke dalam bahasa.

    >>> bantuan (dikt)

    Bantuan dict kelas dalam modul builtin:

    kelas dict (objek)
     | dict () -> kamus kosong baru
     | dict (mapping) -> kamus baru yang diinisialisasi dari objek pemetaan
     | (kunci, nilai) berpasangan
    ...
     |  
     | Dapatkan(...)
     | D. dapatkan (k [, d]) -> D [k] jika k dalam D, kalau tidak d. d default ke Tidak ada.
     |  
    ...
John La Rooy
sumber
22

Menggunakan dict.get

Mengembalikan nilai kunci jika kunci ada di kamus, kalau tidak default. Jika default tidak diberikan, defaultnya adalah None, sehingga metode ini tidak pernah memunculkan KeyError.

Daenyth
sumber
19

Anda harus menggunakan get()metode dari dictkelas

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

Ini akan menghasilkan r == None. Jika kunci tidak ditemukan dalam kamus, fungsi get mengembalikan argumen kedua.

dusktreader
sumber
19
Anda tidak harus lulus Nonesecara eksplisit. Itu adalah default.
Björn Pollex
18

Jika Anda menginginkan solusi yang lebih transparan, Anda bisa subkelas dictuntuk mendapatkan perilaku ini:

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
sumber
2
@marineau: Seperti yang saya sebutkan di komentar untuk jawaban lain, masalah dengan itu defaultdictadalah bahwa ia akan tumbuh setiap kali elemen yang belum ada diminta. Ini tidak selalu diinginkan.
Björn Pollex
@ BjörnPollex Sejauh ini yang elegan, Ada petunjuk tentang cara memperpanjang ini untuk mendukung kedalaman? Maksud saya membuat foo['bar']['test']['sss']untuk kembali, Nonebukan pengecualian, Setelah satu kedalaman itu mulai memberikan TypeErrorbukanKeyError
nehem
@itsneo. Anda dapat membangun seluruh struktur NoneDicts. Ini akan membantu jika hal itu KeyErrorakan terjadi pada objek yang paling dalam. Kalau tidak, masalahnya adalah bahwa sekali Anda mengembalikan Noneobjek, Anda tidak dapat berlangganan lagi. Satu peretasan jelek akan mengembalikan objek lain yang menguji suka None. Namun waspadalah bahwa ini dapat menyebabkan bug yang mengerikan.
magu_
@ BjörnPollex Apakah saya tetap bisa mengubah return dict.get(self, key)ke return super().get(key)? Lalu jika saya memutuskan untuk menggunakan OrderedDict alih-alih dict, misalnya, saya tidak perlu khawatir mengubah beberapa baris kode.
Wood
@ Kayu Ya, itu sebenarnya jauh lebih baik!
Björn Pollex
12

Saya biasanya menggunakan defaultdict untuk situasi seperti ini. Anda menyediakan metode pabrik yang tidak mengambil argumen dan menciptakan nilai ketika melihat kunci baru. Ini lebih berguna ketika Anda ingin mengembalikan sesuatu seperti daftar kosong pada kunci baru ( lihat contoh ).

from collections import defaultdict
d = defaultdict(lambda: None)
print d['new_key']  # prints 'None'
pekerjaan
sumber
19
Masalahnya defaultdictadalah akan terus bertambah setiap kali elemen yang tidak ada diminta.
Björn Pollex
8

Anda bisa menggunakan dictobjek get()metode, seperti orang lain telah disarankan. Atau, tergantung pada apa yang Anda lakukan, Anda mungkin dapat menggunakan try/exceptsuite seperti ini:

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

Yang dianggap sebagai pendekatan yang sangat "Pythonic" untuk menangani kasus ini.

martineau
sumber
7

Solusi satu baris adalah:

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

Ini berguna ketika mencoba menambahkan nilai kamus ke daftar baru dan ingin memberikan default:

misalnya.

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

Seperti yang orang lain katakan di atas, Anda dapat menggunakan get ().

Tetapi untuk memeriksa kunci, Anda juga dapat melakukan:

d = {}
if 'keyname' in d:

    # d['keyname'] exists
    pass

else:

    # d['keyname'] does not exist
    pass
Marek P
sumber
Saya sekarang melihat bahwa Anda sudah tahu bagaimana melakukan ini. Saya akan menghapus posting saya, tetapi saya akan meninggalkannya untuk referensi orang lain.
Marek P
4
Pendekatan ini biasanya membutuhkan kunci untuk dicari dua kali ketika itu ada, yang mungkin merupakan alasan untuk getmetode ini.
martineau
0

Saya terkejut dengan apa yang mungkin di python2 vs python3. Saya akan menjawabnya berdasarkan apa yang akhirnya saya lakukan untuk python3. Tujuan saya sederhana: memeriksa apakah respons json dalam format kamus memberikan kesalahan atau tidak. Kamus saya disebut "token" dan kunci saya yang saya cari adalah "kesalahan". Saya mencari kunci "kesalahan" dan jika tidak ada pengaturannya untuk nilai Tidak, maka memeriksa adalah nilai Tidak, jika demikian lanjutkan dengan kode saya. Pernyataan lain akan menangani jika saya memiliki kunci "kesalahan".

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

Jika Anda dapat melakukannya dengan False, maka, ada juga fungsi bawaan hasattr :

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