【问题标题】:Choosing the right design pattern for execution on a dictionary key选择正确的设计模式以在字典键上执行
【发布时间】:2014-09-02 18:31:33
【问题描述】:

首选哪种设计模式?

对于可能有也可能没有名为 'foo' 的键的字典 d...

模式 A

if d.get('foo'):
    func(d.get('foo'))

模式 B

foo = d.get('foo')
if foo:
    func(foo)

我认为我更喜欢模式 A 的 2 行方法。第二次查找是否比模式 B 的额外分配成本更高?

【问题讨论】:

    标签: python design-patterns dictionary


    【解决方案1】:

    你正在写的两件事完全不同。

    第一个使用字符串'foo' 作为func 的参数。

    第二个使用d['foo'] 中的任何值作为func 的参数。

    哪一个是对的,完全取决于哪一个是你真正想做的。


    在您编辑的版本中,进行两次查找是愚蠢的。

    当然,它“成本更高”——您必须对 'foo' 进行两次散列运算,并查找该散列值(并可能探测几次)两次,其成本是执行一次的两倍。但是这种性能成本在任何实际程序中都不太重要。 (即使您的密钥散列成本很高——三个字符的字符串不是这样——大多数散列成本很高的类型都会在第一次缓存散列值......)

    一个更现实的潜在问题是,如果您想让您的代码成为多线程或只是可重入的,那么您就无缘无故地添加了竞争条件。

    但是,更重要的是,重复自己总是会带来出错的机会,因为您必须完全正确地重复自己,而且当您没有这样做时并不总是很明显,尤其是当您稍后编辑其中一个副本时。 (你一开始就把问题弄错了,这是一个很好的论据……)出于同样的原因,你还为人们提供了错误阅读代码的机会,或者只是偶然阅读它并不得不考虑一些事情这应该是显而易见的。这就是为什么 DRY(不要重复自己——除非你有充分的理由这样做)是编程的基本原则。


    话虽如此,第一个最好写成if 'foo' in d:。如果您实际上不需要该值,请不要检索它。

    第二个最好用 EAFP 而不是 LBYL:

    try:
        func(d['foo'])
    except KeyError:
        pass
    

    或者,在 Python 3.5 中:

    func(d['foo']) except KeyError: None
    

    【讨论】:

    • 我打错了。我已经按照我的初衷进行了更新。
    • 是的。很好的例子说明了为什么 DRY 很重要。带有in 运算符的模式 A 听起来要好得多。
    猜你喜欢
    • 2018-02-18
    • 2019-11-05
    • 1970-01-01
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多