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

这个函数的用途是什么?如果我想在字典中找到一个与键相关的值,我可以只做dict[key],它返回相同的东西:

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

当前回答

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

类似地,如果您试图从列表中捕获单个值,我将使用“.join(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条件

其他回答

Get接受第二个可选值。如果指定的键在您的字典中不存在,则将返回此值。

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

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

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

它允许你在缺少键时提供一个默认值:

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)

会。

这个函数的用途是什么?

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

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

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

有了这些信息,可能很容易得出这样的结论:. Get在某种程度上比方括号索引更安全更好,应该总是使用而不是方括号查找,就像在Python中停止使用方括号符号来获取字典的值中所争论的那样,即使在他们期望查找成功的常见情况下(即永远不会引发KeyError)。

博客文章的作者认为。get“保护你的代码”:

请注意,试图引用一个不存在的术语会导致KeyError。这可能会导致严重的问题,特别是在处理不可预测的业务数据时。 虽然我们可以用try/except或if语句来包装语句,但对字典术语的如此关注很快就会堆积起来。

确实,在不常见的情况下,null (None)-合并或以其他方式填充一个缺失的值来处理不可预测的动态数据,明智部署的.get是一个有用的python简化工具,用于dct:和try/except块中笨拙的if键,这些块仅存在于设置默认值时,键可能缺失,作为程序行为规范的一部分。

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

程序员常犯的一个错误是认为异常会引起头痛,并试图抑制它们,使用诸如在try…除了:传递块。他们后来意识到,真正令人头疼的是,在出现故障时从未发现应用程序逻辑被破坏,也从未部署过被破坏的应用程序。更好的编程实践是包含所有程序不变量的断言,例如必须在字典中的键。

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

Error category Relative ease of debugging
Compile-time error Easy; go to the line and fix the problem
Runtime exception Medium; control needs to flow to the error and it may be due to unanticipated edge cases or hard-to-reproduce state like a race condition between threads, but at least we get a clear error message and stack trace when it does happen.
Silent logical error Difficult; we may not even know it exists, and when we do, tracking down state that caused it can be very challenging due to lack of locality and potential for multiple assertion breaches.

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

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

一些语言,如JS, Java, Rust和Go,在默认情况下为它们的映射使用回退行为(在许多情况下,不提供抛出/抛出替代方案),但Python默认抛出,以及其他语言,如c#。Perl/PHP发出未初始化值警告。

对所有字典访问不加区别地应用.get,即使是那些预计不会失败的访问,也没有处理None(或任何默认值)的回退方法,在代码中肆意地运行,这几乎破坏了Python对这类错误的运行时异常安全网,使潜在的错误变得沉默或间接。

偏爱方括号查找的其他支持原因(偶尔会在需要默认值的地方适当放置.get):

Prefer writing standard, idiomatic code using the tools provided by the language. Python programmers usually (correctly) prefer brackets for the exception safety reasons given above and because it's the default behavior for Python dicts. Always using .get forfeits intent by making cases when you expect to provide a default None value indistinguishable from a lookup you assert must succeed. Testing increases in complexity in proportion to the new "legal" program paths permitted by .get. Effectively, each lookup is now a branch that can succeed or fail -- both cases must be tested to establish coverage, even if the default path is effectively unreachable by specification (ironically leading to additional if val is not None: or try for all future uses of the retrieved value; unnecessary and confusing for something that should never be None in the first place). .get is a bit slower. .get is harder to type and uglier to read (compare Java's tacked-on-feel ArrayList syntax to native-feel C# Lists or C++ vector code). Minor.

一些语言,如c++和Ruby提供了替代方法(分别为at和fetch)来选择进入,从而在错误访问时抛出错误,而c#提供了选择进入的回退值TryGetValue,类似于Python的get。

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

但正如我所说,Python(以及c#)通过将assert选项作为默认选项,比这些语言做得更好。在出现故障时,不使用它来报告合同违规行为,而不加区别地使用。get,是一种安全性和表达性的损失。

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

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

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