Python:如果键入字典与尝试/除了

我有一个关于成语和可读性的问题,在这个特殊情况下似乎有一个Python哲学的冲突:

我想从字典B中build立字典A.如果在B中不存在特定的密钥,则不做任何事情并继续。

哪种方式更好?

try: A["blah"] = B["blah"] except KeyError: pass 

要么

 if "blah" in B: A["blah"] = B["blah"] 

“请求宽恕”与“简单明确”。

哪个更好?为什么?

exception不是条件。

有条件的版本更清晰。 这很自然:这是直接的stream程控制,这是条件的devise,而不是例外。

在循环中执行这些查找时,exception版本主要用作优化:对于某些algorithm,它允许从内部循环中消除testing。 这里没有这个好处。 它有一个小优点,就是避免了两次说"blah" ,但是如果你做了很多这些,你应该有一个helper move_key函数。

一般来说,我强烈build议默认情况下使用条件版本,除非你有一个特定的原因不要。 条件是做这件事的显而易见的方法,通常强烈build议select一种解决scheme而不是另一种解决scheme。

还有第三种方法可以避免exception和双重查找,如果查找代价高昂,这可能很重要:

 value = A.get("blah", None) if value is not None: A["blah"] = value 

如果你期望字典包含None值,你可以使用一些更深奥的常量,如NotImplementedEllipsis或者创build一个新的:

 MyConst = object() def update_key(A, B, key): value = B.get(key, MyConst) if value is not MyConst: A[key] = value 

无论如何,使用update()是我最可读的选项:

 a.update((k, b[k]) for k in ("foo", "bar", "blah") if k in b) 

从我的理解,你想要更新字典A与键字,价值对来自字典B

update是一个更好的select。

 A.update(B) 

例:

 >>> A = {'a':1, 'b': 2, 'c':3} >>> B = {'d': 2, 'b':5, 'c': 4} >>> A.update(B) >>> A {'a': 1, 'c': 4, 'b': 5, 'd': 2} >>> 

直接引用Python性能wiki:

除了第一次,每次看到一个单词if语句的testing失败。 如果你数了大量的话,很多可能会出现多次。 在一个值的初始化只发生一次的情况下,这个值的增加会多次出现,使用try语句会更便宜。

所以看来,这两种select都是可行的,取决于情况。 有关更多详细信息,您可能需要查看此链接: 试用 – 除了性能

我认为这里的一般规则是A["blah"]通常是存在的,如果是这样的话 – 除非是好的,否则使用if "blah" in b:

我觉得“试试”在时间上便宜,但“除外”是比较昂贵的。

我想第二个例子是你应该去的,除非这个代码有意义:

 try: A["foo"] = B["foo"] A["bar"] = B["bar"] A["baz"] = B["baz"] except KeyError: pass 

请记住,一旦存在不在B的密钥,代码将立即中止。 如果这个代码有意义,那么你应该使用exception方法,否则使用testing方法。 在我看来,因为它更短,并且清楚地expression了意图,所以比exception方法更容易阅读。

当然,告诉你使用update是正确的。 如果您使用的是支持字典parsing的Python版本,我强烈推荐使用以下代码:

 updateset = {'foo', 'bar', 'baz'} A.update({k: B[k] for k in updateset if k in B}) 

其他语言的规则是为特殊条件保留例外,即在正常使用中不会发生的错误。 不知道该规则如何适用于Python,因为该规则不应该存在StopIteration。

就个人而言,我倾向于第二种方法(但使用has_key ):

 if B.has_key("blah"): A["blah"] = B["blah"] 

这样,每个赋值操作只有两行(而不是try / except),任何抛出的exception都将是真正的错误或者你错过的东西(而不是仅仅访问那些不存在的键) 。

事实certificate(请参阅您的问题的评论), has_key已弃用 – 所以我想最好写成

 if "blah" in B: A["blah"] = B["blah"]