选择正确的设计模式以在字典键上执行

时间:2014-09-02 18:31:33

标签: python design-patterns dictionary

首选哪种设计模式?

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

的密钥

模式A

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

模式B

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

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

1 个答案:

答案 0 :(得分:2)

你写的两件事情完全不同。

第一个使用字符串'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