dict.pop 或 dict.get 和评估

问题描述 投票:0回答:2

考虑以下代码:

>>> def default_answer():
...     print "Default was required!"
...     return 100
... 
>>> g = { 'name': 'Jordan', 'age': 35 }
>>> result = g.get('age', default_answer())
Default was required!
>>> result = g.pop('age', default_answer())
Default was required!

注意,无论

g
是否包含预期的键,default_answer 都会被调用。这在编程上是有意义的,但如果
default_answer
的计算成本很高,这将是一个麻烦(运行大量代码来创建一个将被丢弃的值)。

我能想到写这篇文章而不总是打电话

default_answer
的唯一方法是:

result = g.pop('age', False) or default_answer()

这是最好的方法吗?

(请注意,我知道用具有惰性求值的对象替换

default_answer
也可以解决这个问题的一部分,但这超出了这个问题的范围)。

python short-circuiting
2个回答
10
投票

不,这不是最好的方法,因为

g.pop()
的结果可能是“假”。使用
try
/
except
代替:

try:
    result = g.pop('age')
except KeyError:
    result = default_answer()

这个习语称为 EAFP,由于各种原因通常比 LBYL 更受青睐:

  1. 它避免了两次查找密钥(这对于实际的

    dict
    来说不是问题,但对于其他映射可能不是最佳的)。

  2. 它避免了线程代码中的竞争条件。

  3. 很多人发现它更容易阅读。


2
投票

只要您知道任何 boolean-false 值(不仅是 False,还包括空字符串、空列表等)都应该替换为您的默认值,这是一个不错的方法。您始终可以明确地执行此操作:

if 'age' in g:
    result = g['age']
else:
    result = default_answer()

(或者使用 try/ except 的等效版本,首先读取值并在 except 子句中执行默认值。哪个更好取决于您期望缺失值的情况是常见还是不常见。)

© www.soinside.com 2019 - 2024. All rights reserved.