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
值,你可以使用一些更深奥的常量,如NotImplemented
, Ellipsis
或者创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"]