Neden dict [key] yerine dict.get (anahtar)?


649

Bugün, sözlükte bir anahtar verildiğinde ilişkili değeri döndüren dictyönteme rastladım get.

Bu işlev hangi amaçla yararlıdır? Bir sözlükte bir anahtarla ilişkili bir değer bulmak istersem, yapabilirim dict[key]ve aynı şeyi döndürür:

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

1
dictionary["foo"]ve dictionary.get("foo")farklı davranıyorlar.
Niklas B.

34
dictionary.get("Age") yazma ile aynıdır, dictionary["Age"] or None bu yüzden KeyError istisnasını dolaylı olarak işler
yosemite_k

5
@yosemite_k Burada bir bağlam eksik olabilir, ama dictionary['non-existent key'] or Noneyine KeyErrorde benim için ( v3.6'ya kadar) yükseltmeli ve yükseltmelidir . Ne demek istediğini açıklayabilir misin?
nivk

@nivk dictionary ['varolmayan anahtar'] hata verir ve bu hata açıkça ele alınmalıdır. bunun yerine dictionary.get () (kelimenin tam anlamıyla sözlük ['varolmayan anahtar'] veya Hiçbiri olarak işlev görür) kullanırsa, bu kural dışı durum işlenir.
yosemite_k

Yanıtlar:


991

Anahtar eksikse varsayılan bir değer vermenizi sağlar:

dictionary.get("bogus", default_value)

döner default_value(ne seçerseniz seçin), oysa

dictionary["bogus"]

yükseltir KeyError.

Atlanırsa, default_valueolduğu None, öyle ki

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

Noneaynen geri döner

dictionary.get("bogus", None)

olacaktır.


1
Bu aynı olur dictionary.get("bogus") or my_defaultmu? İnsanların bazı durumlarda kullandığını gördüm ve diğerini (okunabilirlik dışında) yerine kullanmanın herhangi bir avantajı olup olmadığını merak ediyordum
Algoritmatik

15
@MustafaS: Eğer "bogus"bir anahtardır dictionaryve dictionary.get("bogus")bir değere, bir Boole bağlamda yanlış değerlendirir (yani, bir Falsey değeri) döner, örneğin 0 ya da boş bir dize, ''daha sonra dictionary.get("bogus") or my_defaultdeğerlendirmek olur my_defaultise dictionary.get("bogus", my_default)Falsey değeri dönüş olur. Yani hayır, dictionary.get("bogus") or my_defaulteşdeğer değil dictionary.get("bogus", my_default). Hangisinin kullanılacağı arzu ettiğiniz davranışa bağlıdır.
unutbu

3
@MustafaS: Diyelim ki x = {'a':0}. Sonra x.get('a', 'foo')geri döner 0ancak x.get('a') or 'foo'geri döner 'foo'.
unutbu

3
Kullanırken olası bir uyarı dictionary.get('key'): Sözlükteki değerlerin kafa karıştırıcı olması kafa karıştırıcı olabilir None. Dönüş değerini (ikinci isteğe bağlı bağımsız değişken) belirtmeden, anahtarın var olup olmadığını veya değerinin olup olmadığını doğrulamanın bir yolu yoktur None. Bu özel durumda kullanmayı düşünürüm try-except-KeyError.
Aart Goossens

1
Varsayılan değeri belirten ifadenin "get" çağrısında değerlendirildiğini ve bu nedenle her erişimde değerlendirildiğini belirtmek gerekir. Klasik bir alternatif (bir KeyError işleyici veya yüklem kullanarak) varsayılan değeri yalnızca anahtar eksikse değerlendirmektir. Bu, bir kapatma / lambda'nın bir kez oluşturulmasına ve eksik anahtarlarda değerlendirilmesine izin verir.
Tom Stambaugh

142

Nedir dict.get()yöntemi?

Daha önce de belirtildiği gibi, getyöntem eksik değeri gösteren ek bir parametre içerir. Belgelerden

get(key[, default])

Anahtar sözlükte ise anahtarın değerini döndürür, aksi takdirde varsayılan değerdir. Varsayılan belirtilmezse, varsayılan olarak Yok olarak ayarlanır, böylece bu yöntem hiçbir zaman a değerini yükseltmez KeyError.

Bir örnek olabilir

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

Herhangi bir yerde hız iyileştirmeleri var mı?

As söz burada ,

Görünüşe göre, üç yaklaşımın hepsi de, kelime listesinin özelliklerinden aşağı yukarı bağımsız olarak benzer bir performans sergiliyor (birbirlerinin yaklaşık% 10'u içinde).

Daha erken getoldukça yavaştı, Ancak şimdi hız neredeyse varsayılan değeri döndürme ek avantajı ile karşılaştırılabilir. Ancak tüm sorgularımızı silmek için oldukça büyük bir listede test edebiliriz (Testin yalnızca tüm geçerli anahtarları aramayı içerdiğini unutmayın)

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

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

Şimdi bu iki işlevi kullanarak 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

Gördüğümüz gibi, hiçbir işlev araması olmadığından, arama alma işleminden daha hızlıdır. Bu aracılığıyla görülebilirdis

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

Nerede yararlı olacak?

Bir sözlük ararken varsayılan bir değer vermek istediğinizde yararlı olacaktır. Bu azalır

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

Tek bir satıra, val = dic.get(key,def_val)

Nerede yararlı DEĞİLDİR?

KeyErrorBelirli bir anahtarın kullanılamadığını belirten bir geri dönmek istediğinizde . Varsayılan değerin döndürülmesi, belirli bir varsayılan değerin de anahtar olması riskini taşır!

İçinde getbenzer bir özellik olması mümkün mü dict['key']?

Evet! __missing__Bir diksiyon alt sınıfını uygulamamız gerekir .

Örnek bir program

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

Küçük bir gösteri olabilir

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

32
StackOverflow cevaplarının altın standardı!
Apollo Data


1
Bir daha iyi bir test olacağını if k in dict and dict[k]:vs if dict.get(k):. Bu kapaklar durum şu anahtar olup olmadığını kontrol etmek gerekir ve eğer 'evet' ne zaman - ne gibi değer ?, şey: dict = {1: '', 2: 'some value'}.
TitanFighter

7
Böylece yerine bakılmaksızın Sözlük değer varlığın değerlendirilen alır varsayılan değeri unutmayınız dictionary.get(value, long_function())kullanmayı düşünebilirsiniz onedictionary.get(value) or long_function()
Kresimir

Ah @Kresimir, doğru. Karşılaştığım görüşmelerden birinde bu soruyu aldım (bu cevabı ilk olarak gönderdiğimde bunu bilmiyordum). Bana hatırlattığın için teşekkürler.
Bhargav Rao

32

getikinci bir isteğe bağlı değer alır. Belirtilen anahtar sözlüğünüzde yoksa, bu değer döndürülür.

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

İkinci parametreyi vermezseniz Noneiade edilir.

Dizinlemeyi olduğu gibi kullanırsanız dictionary['Year'], varolmayan anahtarlar yükselir KeyError.


19

Python kullanarak web verilerini kazıma konusunda pratik bir örnek vereceğim, çoğu zaman değersiz anahtarlar alacaksınız, bu durumlarda sözlük ['key'] kullanırsanız hata alırsınız, dictionary.get ('tuşu ',' return_otherwise ') sorunu yok.

Benzer şekilde, bir listeden tek bir değer yakalamaya çalışırsanız, '' .join (list) öğesini [0] listesinin aksine kullanırdım.

Umarım yardımcı olur.

İşte pratik bir örnek:

Diyelim ki, ayrıştırmanız gereken bir JOSN dosyası döndüren bir API çağırıyorsunuz. İlk JSON şöyle görünür:

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

İkinci JOSN şöyle:

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

İkinci JSON'da herhangi bir veri yapısında oldukça normal olan "Subdedate_ts" anahtarı eksiktir.

Dolayısıyla, bir anahtardaki o anahtarın değerine erişmeye çalıştığınızda, aşağıdakilerle çağırabilirsiniz:

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

Yapabilirsiniz, ancak ikinci JSON satırı için size bir geri izleme hatası verecektir, çünkü anahtar basitçe mevcut değildir.

Bunu kodlamanın uygun yolu aşağıdaki olabilir:

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

{'x': Hiçbiri} ikinci seviyenin hata almasını önlemek için var. Kazıma yapıyorsanız, elbette koda daha fazla hata toleransı oluşturabilirsiniz. Önce bir if koşulunu belirtmek gibi


2
Bazı kod örnekleri yayınlamış olsaydınız, diğerlerinden daha önce yayınlanan ve muhtemelen kabul edilen iyi bir cevap (benden +1 olsa da)
Mawg, Monica

2
@Mawg Yakın zamanda araştırmam için bir kazıma projem vardı. Bir API çağırıyor ve temel olarak JSON dosyalarını ayrıştırıyordu. RA'mı yaptım. Sahip olduğu önemli sorunlardan biri, birçok anahtarın gerçekten eksik olduğu durumlarda anahtarı doğrudan çağırmaktı. Yukarıdaki metne bir örnek göndereceğim.
kevin

bunun çok boyutlu yönüyle uğraştığınız için teşekkürler! Kulağa, '' x 'yerine {} bile yapabilirsiniz: Yok}
bluppfisk

17

Amaç, anahtar bulunmazsa varsayılan bir değer verebilmenizdir.

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

8

Bu işlev hangi amaçla yararlıdır?

Belirli bir kullanım sözlüğü ile saymaktır. Belirli bir listedeki her öğenin oluşum sayısını saymak istediğinizi varsayalım. Bunu yapmanın yaygın yolu, anahtarların öğeler ve değerlerin yineleme sayısı olduğu bir sözlük oluşturmaktır.

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

.get()Yöntemi kullanarak, bu kodu daha kompakt ve net hale getirebilirsiniz:

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

7

Kullanırken dikkat edilmesi gereken bir şey .get():

Sözlük, çağrıda kullanılan anahtarı içeriyorsa .get()ve değeri ise None, varsayılan bir değer sağlansa bile .get()yöntem geri döner None.

Örneğin, beklendiği gibi Nonedeğil , aşağıdaki dönüşler 'alt_value':

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

.get()'nin ikinci değeri, yalnızca verilen anahtar sözlüğün DEĞİLDİR, söz konusu çağrının dönüş değeri değilse döndürülür None.


1
Bu beni yakaladı: \ Bunu çözmek için bir yolu, d.get('key') or 'alt_value'eğer olabilir biliyorumNone
Daniel Holmes

4

Neden dict [key] yerine dict.get (anahtar)?

0. Özet

İle karşılaştırıldığında dict[key], dict.getbir anahtar ararken bir geri dönüş değeri sağlar.

1. Tanım

get (anahtar [, varsayılan]) 4. Yerleşik Türler - Python 3.6.4rc1 belgeleri

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

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. Çözdüğü sorun.

Olmadan default value, böyle bir istisnayı işlemek için hantal kodlar yazmanız gerekir.

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'

Uygun bir çözüm olarak, dict.getistenmeyen kodların üstünde kaçınarak isteğe bağlı bir varsayılan değer sunar.

3. Sonuç

dict.get sözlükte anahtar yoksa istisna ile başa çıkmak için ek bir varsayılan değer seçeneği vardır


0

Bir avantaj, bu bir avantaj olabilir, eğer var olmayan bir anahtar arıyorsanız, parantez notasyonunu kullandığımız gibi değil, hiçbiri alamayacağız, bu durumda bir hata alacağız:

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

Get yöntemi hakkında havalı olan son şey, varsayılan bir değer için isteğe bağlı ek bir argüman almasıdır, yani bir öğrencinin puan değerini almaya çalışırsak, ancak öğrencinin alabileceğimiz bir puan anahtarı yoksa yerine 0.

Yani bunu (veya benzer bir şeyi) yapmak yerine:

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

Bunu yapabiliriz:

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

-1

Kullanıma bağlı olarak bu getyöntemi kullanmalısınız .

Örnek 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]: ''

Örnek2

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