关于python:为什么用dict.get(key)代替dict[key]?

Why dict.get(key) instead of dict[key]?

今天,我遇到了dict方法get,它在字典中给定了一个键,返回相关的值。

这个函数的用途是什么?如果我想在字典中找到与键关联的值,我只需执行dict[key],它返回相同的内容:

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


它允许您在缺少密钥时提供默认值:

1
dictionary.get("bogus", default_value)

返回default_value(无论您选择它是什么),而

1
dictionary["bogus"]

会增加一个KeyError

如果省略,default_valueNone,这样

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

返回None就像

1
dictionary.get("bogus", None)

会。


What is the dict.get() method?

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

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

一个例子可以是

1
2
3
4
5
6
7
8
9
10
>>> 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相当慢,但现在的速度几乎与返回默认值的额外优势相当。但是为了清除我们所有的查询,我们可以在一个相当大的列表上进行测试(注意,测试只包括查找所有有效的键)

1
2
3
4
5
6
7
def getway(d):
    for i in range(100):
        s = d.get(i)

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

现在使用timeit对这两个函数进行计时。

1
2
3
4
5
>>> 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

正如我们所看到的,查找比get快,因为没有函数查找。这可以通过dis看到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> 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?

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

1
2
3
4
 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']?

对!我们需要在dict子类中实现__missing__

示例程序可以

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

一个小的示范可以是

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


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

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

如果不给出第二个参数,则返回None

如果像在dictionary['Year']中那样使用索引,则不存在的键将引发KeyError


我将给出一个使用python抓取Web数据的实际例子,很多时候你会得到没有值的键,在这种情况下,如果你使用字典['key'],你会得到错误,而dictionary.get('key','return')没有问题。

类似地,如果尝试从列表中捕获单个值,我将使用""联接(列表),而不是列表[0]。

希望它有帮助。

[编辑]下面是一个实用的例子:

比如,您正在调用一个API,它返回一个您需要解析的josn文件。第一个JSON如下所示:

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

第二个约森是这样的:

1
{"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"键,这在任何数据结构中都是很正常的。

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

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

您可以,但它会为第二行JSON提供一个回溯错误,因为这个键根本不存在。

对此进行编码的适当方法可以是:

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

'X':无以避免第二级出错。当然,如果您正在执行抓取,那么可以在代码中嵌入更多的容错性。比如首先指定一个if条件


这样做的目的是,如果找不到键,可以给出一个默认值,这非常有用

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

For what purpose is this function useful?

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

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

使用.get()方法,可以使此代码更加紧凑和清晰:

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


Why dict.get(key) instead of dict[key]?

0。总结

dict[key]相比,dict.get在查找键时提供了一个回退值。

1。定义

GET(键[,默认])4.内置类型-python 3.6.4rc1文档

如果键在字典中,则返回键的值,否则为默认值。如果未给定默认值,则默认为无,因此此方法不会引发keyError。

1
2
3
4
5
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,就必须编写繁琐的代码来处理这种异常。

1
2
3
4
5
6
7
8
9
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引入了一个可选的默认值,避免了上述不明智的代码。

三。结论

如果字典中没有密钥,dict.get有一个额外的默认值选项来处理异常。


  • 如果键不存在,dict.get将默认不返回任何内容,但是如果您对它进行第二个参数,它将返回如果键不存在。

  • 如果密钥不存在,Otoh dict[key]将提升KeyError

以下是一个示例(阅读注释):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> 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]

根据使用情况,应使用此get方法。

实例1

1
2
3
4
5
6
7
8
9
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

1
2
3
4
5
6
7
8
9
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'