dict.pop或dict.get和评估

时间:2012-08-27 18:51:21

标签: python short-circuiting

请考虑以下代码:

>>> 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也可以解决部分问题,但这超出了这个问题的范围。)

2 个答案:

答案 0 :(得分:9)

不,这不是最好的方法,因为g.pop()的结果可能是“假的”。请改用try / except

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

这个成语被称为EAFP,由于各种原因,通常优先于LBYL

  1. 它避免了两次查找密钥(这对于实际的dict来说不是问题,但对于其他映射可能不是最理想的。)

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

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

答案 1 :(得分:2)

只要你知道任何boolean-false值(不只是False,还有空字符串,空列表等)应该用你的默认值替换,这是一种好方法。您可以随时明确地执行此操作:

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

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