Sözlük anahtarı yoksa Hiçbiri döndürme


489

Ben anahtarı varsa bir sözlük değeri almak için bir yol gerekir, ya da yoksa sadece dönün None.

Ancak, KeyErrorvar olmayan bir anahtarı ararsanız Python bir istisna oluşturur. Anahtarı kontrol edebileceğimi biliyorum, ama daha açık bir şey arıyorum. NoneAnahtar yoksa geri dönmenin bir yolu var mı?


74
Sadece kullanmak .get(key)yerine[key]
Gabe

12
Bir dikte bir KeyError istisnası oluşturur. "Return_error" döndürmez.
Ber

3
Python'da anahtara erişmek ve istisnayı yakalamak gayet iyi. Hatta iyi bilinen ve sıklıkla kullanılan bir tasarım modelidir. Bunun yerine Yok'u döndürürseniz, Yok'u bazı durumlarda alakalı olabilecek bir değer olarak saklamak imkansız hale gelir.
Ber

1
Bazen sözlükteki "Hiçbiri" girişlerini ve eksik girişleri aynı şekilde ele almak istersiniz, bu durumda kabul edilen cevap işi iyi yapar gibi görünür.
cib

@ Açıklamak için soruyu düzenledim. Sen de yapabilirdin.
törzsmókus

Yanıtlar:


813

Kullanabilirsiniz dict.get()

value = d.get(key)

hangi Noneeğer dönecektir key is not in d. Ayrıca, aşağıdakiler yerine döndürülecek farklı bir varsayılan değer de sağlayabilirsiniz None:

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

47
NoneAnahtar varsayılan olarak açıkça eşlendiğinde, varsayılan bir geri dönüşe sahip ikinci varyantın yine de döneceğini unutmayın None. İstediğiniz bu değilse, böyle bir şey kullanabilirsiniz d.get(key) or "empty".
cib

15
@cib: İyi nokta, ama çözüm benzer bir sorun vardır - Anahtar herhangi bir "falsy" değerine eşlenir if (gibi [], "", False, 0.0ya da aslında None), sonra çözüm her zaman dönecekti 0. NoneS değerini değer olarak bekliyorsanız , if key in d:kontrolü açıkça yapmanız gerekir .
Tim Pietzcker

1
@cib bunun için alkışlıyor, burada yanlış yaptığım şeyi çözemedim.
wobbily_col

@TimPietzcker - Cevabınızı açıklayabilir misiniz? d.get (anahtar) veya "boş" herhangi bir 'falsy' değerlerine eşlenmesi durumunda "boş" yanılmıyorsam "boş" dır.
MiloMinderbinder

@MiloMinderbinder: geçerli bir anahtar değilse "empty"döndürülür . Eşlenen değeri ile ilgisi yoktur . keydkey
Tim Pietzcker

63

Merak etme. Dilde yerleşiktir.

    >>> yardım (dikte)

    Modül yerleşiklerindeki sınıf dikimi konusunda yardım:

    sınıfta dikte (nesne)
     | dict () -> yeni boş sözlük
     | dict (mapping) -> bir eşleme nesnesinden başlatılan yeni sözlük
     | (anahtar, değer) çiftleri
    ...
     |  
     | almak(...)
     | D.get (k [, d]) -> D [k] D içinde k ise, d. d varsayılanı Hiçbiri'dir.
     |  
    ...

22

kullanım dict.get

Anahtar sözlükte ise, varsayılan değer olarak anahtarın değerini döndürür. Varsayılan belirtilmezse, varsayılan olarak Yok olarak ayarlanır, böylece bu yöntem hiçbir zaman KeyError oluşturmaz.


19

Sen kullanmalıdır get()gelen yöntemini dictsınıfında

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

Bu sonuçlanacaktır r == None. Anahtar sözlükte bulunmazsa, get işlevi ikinci bağımsız değişkeni döndürür.


19
NoneAçıkça geçmek zorunda değilsiniz . Varsayılan değerdir.
Björn Pollex

18

Daha şeffaf bir çözüm istiyorsanız, dictbu davranışı elde etmek için alt sınıf yapabilirsiniz :

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: Başka bir cevaba yapılan bir yorumda bahsettiğim gibi, problem, defaultdicthenüz orada olmayan bir elemanın her talep edildiğinde büyüyeceğidir. Bu her zaman arzu edilmez.
Björn Pollex

@ BjörnPollex Bu çok zarif, Herhangi bir derinliği desteklemek için bunu genişletmek için herhangi bir ipucu? İstisna yerine foo['bar']['test']['sss']geri dönmek demek None, Bir derinlikten sonra TypeErroryerine vermeye başlarKeyError
nehem

@itsneo. Tüm yapıyı inşa edebilirsiniz NoneDicts. Bu KeyError, en içteki nesnede gerçekleşmesi durumunda yardımcı olacaktır. Aksi takdirde sorun, bir Nonenesneyi döndürdüğünüzde artık ona abone olamayacağınızdır. Çirkin bir hack, test eden başka bir nesneyi döndürmek olacaktır None. Ancak bunun korkunç hatalara yol açabileceğine dikkat edin.
magu_

@ BjörnPollex Değiştirmek return dict.get(self, key)uygun return super().get(key)mu? Dict yerine OrderedDict kullanmaya karar verirseniz, örneğin, birden çok kod satırını değiştirme konusunda endişelenmem gerekmez.
Ahşap

@Ahşap Evet, bu aslında çok daha hoş olurdu!
Björn Pollex

12

Genellikle böyle durumlar için bir defaultdict kullanıyorum . Hiçbir argüman almayan ve yeni bir anahtar gördüğünde bir değer oluşturan bir fabrika yöntemi sağlarsınız. Yeni tuşlarda boş bir liste gibi bir şey döndürmek istediğinizde daha kullanışlıdır ( örneklere bakın ).

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

19
Sorun, defaultdictmevcut olmayan bir eleman her istendiğinde büyümeye devam etmesidir.
Björn Pollex

8

Diğerlerinin önerdiği gibi bir dictnesnenin get()yöntemini kullanabilirsiniz . Alternatif olarak, tam olarak ne yaptığınıza bağlı olarak, aşağıdaki try/exceptgibi bir paketi kullanabilirsiniz :

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

Bu davanın ele alınmasında çok "Pitonik" bir yaklaşım olarak kabul edilir.


7

Tek satırlık bir çözüm:

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

Bu, yeni bir listeye sözlük değerleri eklemeye çalışırken ve varsayılan bir değer sağlamak istediğinizde yararlıdır:

Örneğin.

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

5

Diğerlerinin yukarıda söylediği gibi, get () işlevini kullanabilirsiniz.

Ancak bir anahtarı kontrol etmek için şunları da yapabilirsiniz:

d = {}
if 'keyname' in d:

    # d['keyname'] exists
    pass

else:

    # d['keyname'] does not exist
    pass

Şimdi bunu nasıl yapacağınızı bildiğinizi görüyorum. Yazımı silecektim, ancak başkaları için referans olarak bırakacağım.
Marek P

4
Bu yaklaşım genellikle anahtarın orada olduğunda iki kez aranmasını gerektirir, bu muhtemelen getyöntemin sebebidir .
martineau

0

Ben python2 vs python3 mümkün olan tarafından şaşırdım. Ben python3 için ne yaptı sonunda dayalı cevap verecektir. Amacım basitti: sözlük biçimindeki bir json yanıtının hata verip vermediğini kontrol edin. Sözlüğüme "jeton" adı verildi ve aradığım anahtar "hata". Ben anahtar "hata" arıyorum ve orada Yok değerine ayarlama değilse, o zaman kontrol değer Yok, eğer öyleyse benim kod ile devam edin. Başka bir ifade "hata" anahtar varsa işleyecek.

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

-2

Bunu yapabilirseniz False, hasattr yerleşik işlev de vardır:

e=dict()
hasattr(e, 'message'):
>>> False
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.