使用 defaultdict 替换 python 中的 try 和/或 if 语句

ded*_*ded 5 python try-catch defaultdict

我最近发现并开始使用默认字典来替换几个更庞大的结构。我在《Python 之禅》中读到,Python 的关键点之一是“应该有一种——最好只有一种——明显的方法来做到这一点。”

基于该标准(或者更实际地基于内存使用情况或速度)以下哪一项(或完全不同的东西)是最好的?我有预感第一个是正确的,但想听听其他人的意见。

my_dict = defaultdict(int)
for generic in iterable:
    my_dict[generic] +=1
Run Code Online (Sandbox Code Playgroud)

或者:

my_dict = {}
for generic in iterable:
    if generic not in my_dict:
        my_dict[generic] = 1
    else:
        my_dict[generic]+=1
Run Code Online (Sandbox Code Playgroud)

或者:

my_dict = {}
for generic in iterable:
    try:
        my_dict[generic] += 1
    except(KeyError):
        my_dict[generic] = 1
Run Code Online (Sandbox Code Playgroud)

使用 my_dict = defaultdict(list) 和使用附加函数也可以这样说。假设使用多个 for 循环或其他条件,而不是简单地从单个可迭代中计算泛型值,因为这显然会具有不同的功能。

bru*_*ers 2

正如 Paulo Almeida 评论的那样,对于您发布的示例,“明显”的解决方案是使用collections.Counter

from collections import Counter
my_dict = Counter(iterable)
Run Code Online (Sandbox Code Playgroud)

就是这样。

至于您发布的其他片段,假设my_dict[key] += 1仅用于示例,并且您的一般问题是关于“如何最好地填充字典”:collections.defaultdict对于同类字典(所有键的值类型相同)来说,这是正确的选择,其中类型有一个默认值(数字零、空字符串、空列表...)。我能想到的最常见的用例是填充列表(或集合或其他容器)的字典。

现在,当你的问题既没有解决collections.Counter也没有解决时collections.defaultdict,你有三种可能的模式:

  • 之前看
  • 尝试/排除 KeyError
  • dict.setdefault(key, value)

如果您期望密钥已经存在,则 try/ except 解决方案会更快 - try/ except 块设置起来非常快,但在引发异常时成本高昂。就我而言,我不推荐它,除非您非常非常确定您的数据现在是什么样子以及将来会是什么样子。

“先看”解决方案的成本几乎恒定,虽然不是免费的,但仍然相当便宜。这确实是您最安全的选择。

dict.setdefault()解决方案的成本与“先看”解决方案的成本大致相同,但实例化默认对象的成本也恒定,这通常会立即受到影响。几年前这是一种常见的模式,但自从collection.defaultdict出现以来,它的用途相当有限,更不用说几乎没有用了。