Вопрос по python, dictionary – Почему dict.get (ключ) вместо dict [ключ]?

456

Сегодня я наткнулся наdict методget который, учитывая ключ в словаре, возвращает соответствующее значение.

Для чего эта функция полезна? Если я хочу найти значение, связанное с ключом в словаре, я могу просто сделатьdict[key]и возвращает то же самое:

dictionary = {"Name": "Harry", "Age": 17}
dictionary["Name"]
dictionary.get("Name")
dictionary["foo"] а такжеdictionary.get("foo") вести себя по-другому, хотя. Niklas B.
dictionary.get("sex")  так же, как писатьdictionary["sex"] or None  поэтому он неявно обрабатывает исключение KeyError yosemite_k
@nivk dictionary ['несуществующий ключ'] вызывает ошибку, и эта ошибка должна быть явно обработана. если вместо этого вы используете dictionary.get () (который буквально функционирует как словарь ['несуществующий ключ'] или None), то это исключение обрабатывается неявно. yosemite_k
@yosemite_k Возможно, мне здесь не хватает контекста, ноdictionary['non-existent key'] or None должен и до сих пор поднятьKeyError для меня (до v3.6). Можете ли вы объяснить, что вы имеете в виду? nivk

Ваш Ответ

9   ответов
0

get метод.

Example1

In [14]: user_dict = {'type': False}

In [15]: user_dict.get('type', '')

Out[15]: False

In [16]: user_dict.get('type') or ''

Out[16]: ''

Example2

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

What is the dict.get() method?

Как уже упоминалосьget Метод содержит дополнительный параметр, который указывает пропущенное значение.Из документации

get(key[, default])

Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.

Примером может быть

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

Are there speed improvements anywhere?

Как уже упоминалосьВот,

It seems that all three approaches now exhibit similar performance (within about 10% of each other), more or less independent of the properties of the list of words.

Ранееget был значительно медленнее, однако теперь скорость почти сопоставима наряду с дополнительным преимуществом возврата значения по умолчанию. Но чтобы очистить все наши запросы, мы можем протестировать довольно большой список (обратите внимание, что тест включает в себя поиск только всех допустимых ключей)

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

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

Теперь синхронизируем эти две функции, используя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

Как мы видим, поиск выполняется быстрее, чем поиск, так как поиск функции отсутствует. Это можно увидеть через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  

Where will it be useful?

Это будет полезно всякий раз, когда вы хотите указать значение по умолчанию при поиске в словаре. Это уменьшает

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

Для одной строки,val = dic.get(key,def_val)

Where will it be NOT useful?

Всякий раз, когда вы хотите вернутьKeyError заявляя, что конкретный ключ недоступен. Возвращение значения по умолчанию также несет в себе риск того, что определенное значение по умолчанию также может быть ключевым!

Is it possible to have get like feature in dict['key']?

Да! Нам нужно реализовать__missing__ в подклассе dict.

Пример программы может быть

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

Небольшая демонстрация может быть

>>> my_d = MyDict({1:2,2:3})
>>> my_d[1]
2
>>> my_d[3]
>>> repr(my_d[3])
'None'
Золотой стандарт StackOverflow отвечает!
Пожалуйста, помните, что значение по умолчанию оценивается независимо от значения в словаре, поэтому вместоdictionary.get(value, long_function()) можно подумать об использованииdictionary.get(value) or long_function()
Еще один хороший тест будетif k in dict and dict[k]: противif dict.get(k):, Это охватывает ситуацию, когда нам нужно проверить, существует ли ключ, и если «да» - какое значение ?, что-то вроде:dict = {1: '', 2: 'some value'}.
Ах @ Kresimir, правда. Я получил этот вопрос в одном из интервью, с которым я столкнулся (я не знал об этом, когда я первоначально опубликовал этот ответ). Спасибо, что напомнили мне об этом.
2

Одно конкретное использование подсчета со словарем. Предположим, вы хотите подсчитать количество вхождений каждого элемента в данном списке. Обычный способ сделать это - создать словарь, в котором ключи - это элементы, а значения - это число вхождений.

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

Используя метод .get (), вы можете сделать этот код более компактным и понятным:

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

во многих случаях вы получите ключи без значений, в этих случаях вы получите ошибки, если будете использовать словарь [& quot; ключ & apos;], тогда как dictionary.get (& apos) ; key '', 'return_otherwise') не имеет проблем.

Точно так же я бы использовал «.join (список)», а не «список» [0], если вы попытаетесь захватить одно значение из списка.

Надеюсь, поможет.

[Править] Вот практический пример:

Скажем, вы вызываете API, который возвращает файл JOSN, который вам нужно проанализировать. Первый JSON выглядит следующим образом:

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

Второй JOSN выглядит так:

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

Обратите внимание, что во втором JSON отсутствует & quot; submitdate_ts & quot; ключ, который является довольно нормальным в любой структуре данных.

Поэтому, когда вы пытаетесь получить доступ к значению этого ключа в цикле, вы можете вызвать его с помощью следующего:

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

Вы могли бы, но это даст вам ошибку отслеживания для второй строки JSON, потому что ключ просто не существует.

Подходящим способом кодирования этого может быть следующее:

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

{& apos; x & apos ;: None} существует, чтобы избежать получения ошибки на втором уровне. Конечно, вы можете повысить отказоустойчивость в коде, если выполняете очистку. Как сначала указать условие if

@Mawg Недавно у меня был скребковый проект для моего исследования. Это был вызов API и синтаксический анализ файлов JSON. У меня был мой РА сделать это. Одной из ключевых проблем, с которыми он столкнулся, было непосредственное обращение к ключу, когда многие ключи фактически отсутствуют. Я опубликую пример в тексте выше.
Хороший ответ, опубликованный перед любым другим, за который проголосовали бы больше, и, вероятно, был бы принят, если бы вы опубликовали несколько примеров кода (+1 от меня, хотя)
так много JOSN, кто знал ?!
Еще один голос, Кевин, за помощь другим
спасибо за решение многомерного аспекта этого! Похоже, вы можете просто сделать {} вместо {& apos; x & apos ;: None}
26

get принимает второе необязательное значение. Если указанный ключ не существует в вашем словаре, то это значение будет возвращено.

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

Если вы не дадите второй параметр,None будет возвращен.

Если вы используете индексирование как вdictionary['Year']несуществующие ключи подымутKeyError.

0

dict.get will default return nothing if the key doesn't exist, but if you put second argument of it, it will return that if the key does not exist.

OTOH dict[key] will raise KeyError if key does not exist.

Вот пример (читай комментарии):

>>> d={'a':[1,2,3],'b':[4,5,6]} # Create a dictionary
>>> d['c'] # Hoops, error key does not exist
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    d['c']
KeyError: 'c'
>>> d.get('c') # no error because of `get`, so nothing returned
>>> print(d.get('c')) # i print it, oh `None` is the output
None
>>> d.get('c',100) # Okay now i set second argument's value to `100`, hoopa output is `100`
100
>>> d['a'] # Works, key exist
[1, 2, 3]
>>> d.get('a') # work too, key exist
[1, 2, 3]
745

если ключ отсутствует:

dictionary.get("bogus", default_value)

возвращаетсяdefault_value (что бы вы ни выбрали), тогда как

dictionary["bogus"]

подниметKeyError.

Если опущено,default_value являетсяNoneтакой, что

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

возвращаетсяNone как

dictionary.get("bogus", None)

было бы.

Что на самом деле так же, какdictionary.get("bogus"), Я уверен, что вы знаете об этом, но это может быть интересно другим читателям :)
@ Джон: То, что вы описываете, это то, чтоsetdefault делает (очень похожий метод, который ведет себя так же, какget но также сохраняет ценность).
@MustafaS: например, предположим,x = {'a':0}, затемx.get('a', 'foo') возвращается0 ноx.get('a') or 'foo' возвращается'foo'.
@John Нет, значение будет возвращено, но оно не изменитdict, Обратите внимание, что если вы часто используете эту функцию,collections.defaultdict может быть более подходящим.
@MustafaS: если"bogus" ключ вdictionary а такжеdictionary.get("bogus") возвращает значение, которое оценивается как False в логическом контексте (то есть значение Falsey), такое как 0 или пустая строка,'', затемdictionary.get("bogus") or my_default оценил быmy_default в то время какdictionary.get("bogus", my_default) вернул бы значение Falsey. Так нетdictionary.get("bogus") or my_default не эквивалентноdictionary.get("bogus", my_default), Какой из них использовать, зависит от желаемого вами поведения.
1

0. Summary

По сравнению сdict[key], dict.get обеспечивает запасное значение при поиске ключа.

1. Definition

получить (ключ [, по умолчанию])4. Встроенные типы & # x2014; Документация Python 3.6.4rc1

Возвращает значение для ключа, если ключ находится в словаре, иначе по умолчанию. Если default не задано, по умолчанию используется None, поэтому этот метод никогда не вызывает KeyError.

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. Problem it solves.

Если безdefault valueВы должны написать громоздкие коды для обработки такого исключения.

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'

Как удобное решение,dict.get вводит необязательное значение по умолчанию, позволяющее избежать вышеуказанных кодов.

3. Conclusion

dict.get имеет дополнительную опцию значения по умолчанию для исключения, если ключ отсутствует в словаре

14

чтобы вы могли дать значение по умолчанию, если ключ не найден, что очень полезно

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

Похожие вопросы