【问题标题】:Is checking if key is in dictionary and getting it's value in the same "if" safe?检查键是否在字典中并在同一个“if”中获取它的值是否安全?
【发布时间】:2015-09-20 12:03:29
【问题描述】:

我认为这是安全的:

if key in test_dict:
    if test_dict[key] == 'spam':
        print('Spam detected!')

但是这样安全吗?

if key in test_dict and test_dict[key] == 'spam':
    print('Spam detected!')

它应该做同样的事情,因为条件检查在 python 中是惰性的。它不会尝试获取值(并引发异常,因为字典中没有这样的键),因为第一个条件已经不满足。但是我可以依靠懒惰并在我的程序中使用第二个示例吗?

【问题讨论】:

  • 是的,两个 sn-ps 都是等效的并且“安全”。

标签: python python-3.x dictionary


【解决方案1】:

是的,这是安全的,如果第一个表达式的结果为 False,Python 会短路,即它不会评估 if 条件中的第二个表达式。

但更好的方法是使用 .get() ,如果 key 不存在于字典中,则返回 None 。示例 -

if test_dict.get(key) == 'spam':
    print('Spam detected!')

【讨论】:

  • 不等价 - 垃圾邮件密钥的值可能为“无”。
  • 在这种情况下以及它的等价物,条件都不会被满足。 None 不等于垃圾邮件。
  • @AnandSKumar 所以,唯一不起作用的情况是当我搜索 None 时?
  • 是的,但即使在这种情况下,.get() 也接受第二个参数,如果未找到密钥,则在未指定默认参数(第二个参数)时默认返回该参数, None 被返回。在检查 None 时,您可以使用不同的默认值。但是,如果您正在检查 key 是否存在于字典中,使用in 会更好。
  • @PadraicCunningham 只有一个条件/表达式?
【解决方案2】:

and test_dict[key] == 'spam': 仅在 if key in test_dictTrue 时才会被评估,它的行为与您嵌套 if 的第一个代码完全相同。

当你使用and时,表达式的两边都必须是True,所以如果key in test_dict返回False,那么代码就会短路。

使用and 方法实际上是最有效的,尤其是当表达式的左侧为 False 时:

In [13]: d = {k:k for k in range(10000)}
In [14]: timeit 99999 in d and d[100] == "foo"
10000000 loops, best of 3: 48.2 ns per loop

In [15]: timeit d.get(9000) == "foo" 
10000000 loops, best of 3: 155 ns per loop
In [16]: timeit 100  in d and d[100] == "foo
10000000 loops, best of 3: 119 ns per loo    
In [17]: timeit d.get(100) == "foo"
10000000 loops, best of 3: 141 ns per loop

【讨论】:

  • 是的,但更有效的方法是d[100] == "foo",但除了舍入它之外,还可以尝试一下。除非大多数键不在字典中。
猜你喜欢
  • 1970-01-01
  • 2012-11-26
  • 2012-12-28
  • 1970-01-01
  • 1970-01-01
  • 2014-09-16
  • 1970-01-01
  • 2013-01-04
  • 1970-01-01
相关资源
最近更新 更多