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

ste*_*tla 553 python dictionary

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

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

dictionary = {"Name": "Harry", "Age": 17}
dictionary["Name"]
dictionary.get("Name")
Run Code Online (Sandbox Code Playgroud)

unu*_*tbu 870

如果缺少密钥,它允许您提供默认值:

dictionary.get("bogus", default_value)
Run Code Online (Sandbox Code Playgroud)

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

dictionary["bogus"]
Run Code Online (Sandbox Code Playgroud)

会提出一个KeyError.

如果省略,default_value则是None这样的

dictionary.get("bogus")  # <-- No default specified -- defaults to None
Run Code Online (Sandbox Code Playgroud)

回报None就像

dictionary.get("bogus", None)
Run Code Online (Sandbox Code Playgroud)

将.

  • @MustafaS:如果``bogus``是`dictionary`和`dictionary.get("bogus")中的键,`返回一个在布尔上下文中计算为False的值(即Falsey值),如0或者空字符串,`''`,然后`dictionary.get("bogus")或my_default`将评估为`my_default`而`dictionary.get("bogus",my_default)`将返回Falsey值.所以不,`dictionary.get("bogus")或my_default`不等同于`dictionary.get("bogus",my_default)`.使用哪个取决于您想要的行为. (12认同)
  • 使用 `dictionary.get('key')` 时的一个可能警告:如果字典中的值是 `None`,可能会造成混淆。如果不指定返回值(第二个可选参数),就无法验证键是否不存在或其值为“无”。在这种特定情况下,我会考虑使用“try-except-KeyError”。 (7认同)
  • @John不,该值将被返回,但它不会修改`dict`.请注意,如果您经常使用此功能,那么`collections.defaultdict`可能更合适. (3认同)
  • @John:你所描述的是`setdefault`的作用(一种非常类似于`get`的方法,但也保存了值). (2认同)
  • @MustafaS:例如,假设`x = {'a':0}`.然后`x.get('a','foo')`返回`0`但是`x.get('a')或'foo'`返回''foo'`. (2认同)
  • 值得注意的是,指定默认值的表达式是在“get”调用中计算的,因此在每次访问时都会计算。一个经典的替代方案(使用 KeyError 处理程序或谓词)是仅在键丢失时才评估默认值。这允许创建一次闭包/lambda 并在任何丢失的键上进行评估。 (2认同)
  • @AartGoossens 或者您可以使用“if 'key' indictionary”,以避免使用“try- except”并使代码更易于理解。 (2认同)

Bha*_*Rao 118

dict.get()方法是什么?

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

get(key[, default])
Run Code Online (Sandbox Code Playgroud)

如果key在字典中,则返回key的值,否则返回default.如果未给出default,则默认为None,因此此方法永远不会引发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
Run Code Online (Sandbox Code Playgroud)

是否有速度提升?

这里提到的,

现在看来,所有三种方法都表现出相似的性能(在彼此的约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]
Run Code Online (Sandbox Code Playgroud)

现在使用这两个函数计时 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
Run Code Online (Sandbox Code Playgroud)

我们可以看到查找比get更快,因为没有函数查找.这可以看出来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  
Run Code Online (Sandbox Code Playgroud)

它会在哪里有用?

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

 if key in dic:
      val = dic[key]
 else:
      val = def_val
Run Code Online (Sandbox Code Playgroud)

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

它在哪里没用?

每当您想要返回一个KeyError说明特定密钥不可用时.返回默认值也会带来特定默认值也可能是关键的风险!

是否有可能有get相似的功能dict['key']

是! 我们需要__missing__在dict子类中实现它.

一个示例程序可以

class MyDict(dict):
    def __missing__(self, key):
        return None
Run Code Online (Sandbox Code Playgroud)

一个小型的演示可以

>>> my_d = MyDict({1:2,2:3})
>>> my_d[1]
2
>>> my_d[3]
>>> repr(my_d[3])
'None'
Run Code Online (Sandbox Code Playgroud)

  • StackOverflow的黄金标准答案! (25认同)
  • 请记住,无论值是否在字典中,都会评估默认值,因此可以考虑使用`dictionary.get(value)或long_function()来代替`dictionary.get(value,long_function())` (5认同)
  • @Kresimir这两种方法不一样,因为`None`或False-y值将默认,而`dictionary.get()`仅在缺少时返回默认值。 (2认同)

Fal*_*gel 26

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

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

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

如果使用索引作为dictionary['Year'],则不存在的键将引发KeyError.


kev*_*vin 18

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

同样,如果你试图从列表中捕获一个值,我会使用'.join(list)而不是list [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"}}
Run Code Online (Sandbox Code Playgroud)

第二个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"}}
Run Code Online (Sandbox Code Playgroud)

请注意,第二个JSON缺少"submitdate_ts"键,这在任何数据结构中都很正常.

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

for item in API_call:
    submitdate_ts = item["bids"]["submitdate_ts"]
Run Code Online (Sandbox Code Playgroud)

你可以,但它会给你第二个JSON行的追溯错误,因为该键根本不存在.

对此进行编码的适当方式可能如下:

for item in API_call:
    submitdate_ts = item.get("bids", {'x': None}).get("submitdate_ts")
Run Code Online (Sandbox Code Playgroud)

{'x':None}可以避免第二级出错.当然,如果你正在进行抓取,你可以在代码中建立更多的容错能力.就像首先指定if条件一样

  • 一个很好的答案,发布在其他任何一个之前,如果你发布了一些代码示例(虽然我来自+1),这些答案可能会更多,并且可能被接受 (2认同)
  • @Mawg我最近为我的研究做了一个刮刮项目.它主要是调用API并解析JSON文件.我让我的RA做到了.他遇到的一个关键问题是直接调用密钥,而实际上缺少许多密钥.我将在上面的文本中发布一个示例. (2认同)

hac*_*ist 15

目的是如果找不到密钥,您可以给出默认值,这非常有用

dictionary.get("Name",'harry')
Run Code Online (Sandbox Code Playgroud)


Col*_*cks 14

使用时要注意的一个问题.get()

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

例如,以下返回None'alt_value'可能不像预期的那样:

d = {'key': None}
assert None is d.get('key', 'alt_value')
Run Code Online (Sandbox Code Playgroud)

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

  • 更像是一个陷阱' (7认同)
  • 这个让我明白了:\ 解决这个问题的一种方法是使用 `d.get('key') 或 'alt_value'` 如果你知道它可能是 `None` (3认同)

ggo*_*len 12

其他答案已经清楚地解释了字典括号键控之间的区别,.get并提到了一个相当无害的陷阱None默认值也是有效键

考虑到这些信息,可能会得出这样的结论:它.get在某种程度上比括号索引更安全、更好,并且应该始终使用而不是括号查找,如停止使用方括号表示法在 Python 中获取字典的值中所述,即使在常见情况下他们期望查找成功(即永远不会提出KeyError)。

该博文的作者认为.get“保护您的代码”:

请注意尝试引用不存在的术语如何导致KeyError. 这可能会引起严重的麻烦,尤其是在处理不可预测的业务数据时。

虽然我们可以将语句包装在try/exceptif语句中,但对字典术语的如此多的关注很快就会堆积起来。

确实,在null ( None) 合并或以其他方式填充缺失值以处理不可预测的动态数据的罕见情况下,明智地部署.get是一种有用且 Python 的速记工具,适用于仅在以下情况下设置默认值的笨拙if key in dct:try/except块:作为程序行为规范的一部分,该密钥可能会丢失。

但是,替换所有括号字典查找(包括那些您断言必须成功的查找).get是另一回事。这种做法有效地降低了一类运行时错误的级别,这些错误有助于将错误揭示为静默的非法状态场景,而这些场景往往更难以识别和调试。

程序员中的一个常见错误是认为异常会导致头痛,并试图使用诸如将代码包装在try...except: pass中之类的技术来抑制它们。他们后来意识到,真正令人头痛的是永远不会在故障点看到应用程序逻辑的破坏并部署损坏的应用程序。更好的编程实践是接受所有程序不变量的断言,例如必须位于字典中的键。

错误安全的层次结构大致如下:

错误类别 调试相对容易
编译时错误 简单的; 去一线解决问题
运行时异常 中等的; 控制需要流向错误,这可能是由于意外的边缘情况或难以重现的状态(例如线程之间的竞争条件)造成的,但至少我们在错误发生时得到了清晰的错误消息和堆栈跟踪。
无声的逻辑错误 难的; 我们甚至可能不知道它的存在,当我们知道时,由于缺乏局部性和可能出现多个断言违规,追踪导致它的状态可能非常具有挑战性。

当编程语言设计者谈论程序安全时,一个主要目标是通过将运行时错误提升为编译时错误并将静默逻辑错误提升为运行时异常或(理想情况下)编译时错误来暴露而不是抑制真正的错误。

Python 在设计上是一种解释性语言,严重依赖于运行时异常而不是编译器错误。默认情况下会引发缺少方法或属性、非法类型操作(例如1 + "a"越界)或缺少索引或键。

某些语言(例如 JS、Java、Rust 和 Go)默认情况下对其映射使用后备行为(并且在许多情况下,不提供 throw/raise 替代方案),但 Python 以及 C# 等其他语言默认情况下会抛出异常。Perl/PHP 发出未初始化值警告。

对所有字典访问不加区别地应用.get,即使是那些预计不会失败并且没有后备处理None(或使用任何默认值)通过代码运行的字典访问,几乎抛弃了此类的 Python 运行时异常安全网错误、消除潜在错误或增加间接性。

更喜欢括号查找的其他支持原因(偶尔,.get在预期默认值的情况下):

  • 更喜欢使用该语言提供的工具编写标准、惯用的代码。由于上面给出的异常安全原因,Python 程序员通常(正确地)更喜欢括号,因为它是 Python 字典的默认行为。
  • .get当您希望提供与None您断言必须成功的查找无法区分的默认值时,始终使用放弃意图。
  • 测试的复杂性与 . 所允许的新“合法”程序路径成比例地增加.get。实际上,每个查找现在都是一个可能成功或失败的分支——这两种情况都必须经过测试才能建立覆盖范围,即使按照规范实际上无法访问默认路径(具有讽刺意味的是,这会导致检索值的额外if val is not None:try所有未来使用;不必要并混淆一些本来不应该放在首位None的东西)。
  • .get就是慢了一点
  • .get更难输入,也更难读(将 Java 的附加ArrayList语法与本机感觉的 C#Lists或 C++ 矢量代码进行比较)。次要的。

C++ 和 Ruby 等一些语言提供了替代方法(分别为atfetch)来选择在错误访问时抛出错误,而 C# 则提供TryGetValue类似于 Python 的选择加入回退值get

由于 JS、Java、Ruby、Go 和 Rust 默认将后备方法烘焙.get到所有哈希查找中,因此人们可能会认为,它不会那么糟糕。确实,这并不是语言设计者面临的最大问题,并且无抛出访问版本有很多用例,因此跨语言没有达成共识也就不足为奇了。

但正如我所说,Python(以及 C#)通过将断言选项设置为默认选项,比这些语言做得更好。.get如果不加选择地全面使用它来报告失败时的合同违规行为,就会丧失安全性和表现力。


jet*_*guy 5

此功能用于什么目的?

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

fruits = ['apple', 'banana', 'peach', 'apple', 'pear']
d = {}
for fruit in fruits:
    if fruit not in d:
        d[fruit] = 0
    d[fruit] += 1
Run Code Online (Sandbox Code Playgroud)

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

for fruit in fruits:
      d[fruit] = d.get(fruit, 0) + 1
Run Code Online (Sandbox Code Playgroud)

  • 虽然这是事实,但请记住“d = defaultdict(int)”甚至更清晰。内循环变为“d[fruit] += 1”。话又说回来,“collections.Counter”可能比“defaultdict”版本更好。如果您不想将“Counter”或“defaultdict”转换回“dict”或类似的东西,“.get”版本可能仍然有用。 (2认同)

Alg*_*bra 5

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

0. 总结

与 相比dict[key]dict.get在查找键时提供后备值。

一、定义

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

如果键在字典中,则返回键的值,否则返回默认值。如果未给出默认值,则默认为 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'
Run Code Online (Sandbox Code Playgroud)

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'
Run Code Online (Sandbox Code Playgroud)

作为一个方便的解决方案,dict.get引入了一个可选的默认值,避免了上面笨拙的代码。

3. 结论

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


אנו*_*ימי 5

一个区别(这可能是一个优点)是,如果我们正在寻找一个不存在的键,我们将得到 None,而不是像我们使用方括号表示法时那样,在这种情况下我们会抛出错误:

print(dictionary.get("address")) # None
print(dictionary["address"]) # throws KeyError: 'address'
Run Code Online (Sandbox Code Playgroud)

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

因此,不要这样做(或类似的事情):

score = None
try:
    score = dictionary["score"]
except KeyError:
    score = 0
Run Code Online (Sandbox Code Playgroud)

我们做得到:

score = dictionary.get("score", 0)
# score = 0
Run Code Online (Sandbox Code Playgroud)


dsh*_*han 5

我没有看到提到的另一个用例是作为,和key等函数的参数。该方法允许根据键的值返回键。sortedmaxminget

>>> ages = {"Harry": 17, "Lucy": 16, "Charlie": 18}
>>> print(sorted(ages, key=ages.get))
['Lucy', 'Harry', 'Charlie']
>>> print(max(ages, key=ages.get))
Charlie
>>> print(min(ages, key=ages.get))
Lucy
Run Code Online (Sandbox Code Playgroud)

感谢对另一个问题的回答提供了这个用例!