今天,我遇到了dict方法get,它在字典中给定一个键,返回相关的值。
这个函数的用途是什么?如果我想在字典中找到一个与键相关的值,我可以只做dict[key],它返回相同的东西:
dictionary = {"Name": "Harry", "Age": 17}
dictionary["Name"]
dictionary.get("Name")
今天,我遇到了dict方法get,它在字典中给定一个键,返回相关的值。
这个函数的用途是什么?如果我想在字典中找到一个与键相关的值,我可以只做dict[key],它返回相同的东西:
dictionary = {"Name": "Harry", "Age": 17}
dictionary["Name"]
dictionary.get("Name")
当前回答
有一个区别,这可能是一个优势,如果我们正在寻找一个不存在的键,我们将得到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
其他回答
它允许您提供一个默认值,而不是在没有找到该值时得到一个错误。像这样的劝说代码:
class dictionary():
def get(self,key,default):
if self[key] is not found :
return default
else:
return self[key]
使用.get()时需要注意的一个问题:
如果字典包含调用.get()中使用的键,且其值为None,则.get()方法将返回None,即使提供了默认值。
例如,下面返回None,而不是'alt_value',这可能是预期的:
d = {'key': None}
assert None is d.get('key', 'alt_value')
.get()的第二个值仅在提供的键不在字典中时才返回,而不是在该调用的返回值为None时才返回。
在Python 3.8及以后版本中,字典get()方法可以与赋值表达式中的walrus操作符:=一起使用,以进一步减少代码:
if (name := dictonary.get("Name")) is not None
return name
使用[]而不是get()将需要将代码包装在try/except块中并捕获KeyError(未显示)。如果没有walrus操作符,您将需要另一行代码:
name = dictionary.get("Name")
if (name is not None)
return name
其他回答清楚地解释了字典括号键控和.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,是一种安全性和表达性的损失。
这个函数的用途是什么?
一个特别的用法是用字典计数。让我们假设您想要计算给定列表中每个元素的出现次数。常见的方法是创建一个字典,其中键是元素,值是出现的次数。
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