为什么用dict.get(key)而不是dict [key]?


649

今天,我遇到了该dict方法get,给定字典中的键,该方法将返回关联的值。

此功能用于什么目的?如果我想找到与字典中的键相关联的值,我可以这样做dict[key],并且它返回相同的内容:

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

1
dictionary["foo"]dictionary.get("foo")表现不同。
Niklas B.

33
dictionary.get("Age") 与编写相同,dictionary["Age"] or None 因此它隐式处理KeyError异常
yosemite_k

5
@yosemite_k我在这里可能会缺少一些上下文,但是dictionary['non-existent key'] or None应该并且仍然会KeyError为我提出一个(最多v3.6)。你能解释你的意思吗?
nivk

@nivk dictionary ['non-existent key']引发错误,并且应该显式处理该错误。相反,如果您使用dictionary.get()(其字面意义为dictionary ['不存在键']或None),则将隐式处理该异常。
yosemite_k

Answers:


990

如果密钥丢失,它允许您提供默认值:

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)

将。


1
这会和dictionary.get("bogus") or my_default吗?我见过人们在某些情况下使用它,而我想知道使用一个而不是另一个是否有优势(可读性除外)
Algorithmical

15
@MustafaS:如果"bogus"是,dictionarydictionary.get("bogus")返回一个在布尔上下文中(例如Falsey值)为False的值(例如0或空字符串)''dictionary.get("bogus") or my_default则将求值为,my_defaultdictionary.get("bogus", my_default)将返回Falsey值。所以不,dictionary.get("bogus") or my_default不等于dictionary.get("bogus", my_default)。使用哪种取决于您想要的行为。
unutbu 2015年

3
@MustafaS:例如,假设x = {'a':0}。然后x.get('a', 'foo')返回,0x.get('a') or 'foo'返回'foo'
unutbu 2015年

3
使用时可能需要注意的一件事dictionary.get('key'):如果字典中的值是,可能会造成混淆None。如果不指定返回值(第二个可选参数),则无法验证键是否不存在或键的值是否为None。在这种情况下,我会考虑使用try-except-KeyError
Aart Goossens

1
值得注意的是,用于指定默认值的表达式是在“ get”调用中求值的,因此在每次访问时都会求值。一种经典的替代方法(使用KeyError处理程序或谓词)是仅在缺少键时才评估默认值。这样就可以一次创建一个闭包/ lambda,并根据缺少的键进行评估。
汤姆·斯坦博

142

什么dict.get()方法?

如前所述,该get方法包含一个附加参数,指示缺少的值。从文档中

get(key[, default])

如果key在字典中,则返回key的值,否则返回默认值。如果未提供default,则默认为None,因此此方法永远不会引发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

哪里有速度改进?

如前所述这里

似乎所有这三种方法现在都表现出相似的性能(彼此之间约占10%),或多或少地与单词列表的属性无关。

以前的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  

在哪里有用?

每当您要查找字典时都想提供默认值时,它将很有用。这减少了

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

一行 val = dic.get(key,def_val)

在哪里没有用?

每当您想返回 KeyError说明该特定键不可用时。返回默认值还会带来一个风险,即某个默认值也可能是键!

是否有可能具有get类似功能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'

32
StackOverflow的黄金标准答案!
Apollo


1
还有一个很好的考验将是if k in dict and dict[k]:VS if dict.get(k):。这涵盖了当我们需要检查密钥是否存在以及是否需要“是”(什么值?)的情况,例如:dict = {1: '', 2: 'some value'}
TitanFighter

7
请记住,不管字典中的值是什么,默认值都会被求值,因此 dictionary.get(value, long_function())可以考虑使用dictionary.get(value) or long_function()
Kresimir,

啊@Kresimir,是的。我确实在所面对的一次采访中遇到了这个问题(当我最初发布此答案时,我还不知道这个问题)。感谢您提醒我。
巴尔加夫(Bhargav Rao)

32

get采用第二个可选值。如果字典中不存在指定的键,则将返回此值。

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

如果不提供第二个参数,None将返回。

如果您按这种方式使用索引dictionary['Year'],则不存在的键将引发KeyError


19

我将举一个使用python抓取Web数据的实际示例,很多时候,您将获得没有值的键,在这些情况下,如果您使用dictionary ['key']会出错,而dictionary.get('key ','return_otherwise')没问题。

同样,如果您尝试从列表中捕获单个值,我将使用''.join(list)而不是list [0]。

希望能帮助到你。

[编辑]这是一个实际示例:

假设您正在调用一个API,该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缺少“ submitdate_ts”键,这在任何数据结构中都是很正常的。

因此,当您尝试循环访问该键的值时,可以使用以下命令调用它:

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

{'x':None}可以避免第二级出错。当然,如果您执行抓取操作,则可以在代码中内置更多的容错功能。就像首先指定一个if条件


2
如果您已经发布了一些代码示例(不过,我提供了+1),那么在其他任何版本之前发布的一个好的答案应该会更多,并且可能会被接受
Mawg说恢复Monica

2
@Mawg我最近有一个研究项目。它正在调用一个API并基本上解析JSON文件。我让我的RA做到了。他遇到的关键问题之一是在实际上缺少许多钥匙时直接呼叫钥匙。我将在上面的文本中发布一个示例。
凯文

感谢您解决此问题的多维方面!听起来您甚至可以只用{}代替{'x':None}
bluppfisk

17

目的是如果找不到密钥,则可以提供默认值,这非常有用

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

8

此功能用于什么目的?

一种特殊用法是用字典计数。假设您要计算给定列表中每个元素的出现次数。这样做的常见方法是制作一个字典,其中键是元素,值是出现的次数。

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

7

使用时要注意的陷阱 .get()

如果字典包含在调用中使用的键,.get()并且其值为None,则该.get()方法将返回None即使提供了默认值。

例如,以下返回None,不是'alt_value'预期的:

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

.get()仅当提供的键不在字典中时,才返回的第二个值,如果该调用的返回值为,则不返回None


1
解决这个问题的一种方法是让d.get('key') or 'alt_value'您知道是否可能None
Daniel Holmes,

4

为什么用dict.get(key)而不是dict [key]?

0.总结

与相比dict[key]dict.get查找关键字时提供了一个后备值。

1.定义

get(key [,default]) 4.内置类型-Python 3.6.4rc1文档

如果key在字典中,则返回key的值,否则返回默认值。如果未提供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.解决的问题。

如果没有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.结论

dict.get 如果字典中没有键,则还有一个附加的默认值选项来处理异常


0

一个不同可能是一个优点,那就是,如果我们正在寻找一个不存在的键,我们将得到None,这与使用方括号表示法不同,在这种情况下,我们将抛出错误:

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

关于get方法的最后一件很酷的事情是,它接收了一个默认值的附加可选参数,也就是说,如果我们尝试获取学生的分数值,但是该学生没有分数键,我们可以获取改为0。

因此,不要这样做(或类似操作):

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

我们做得到:

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

-1

根据用法应使用此get方法。

例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]: ''

例2

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'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.