用python更新字典的最快方法

2024-04-25 04:34:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一本字典和一个可能的词条。我知道[foo]应该等于x,但我不知道是否已经定义了[foo]。在任何情况下,如果定义了[foo],则表示它已经具有正确的值。

执行速度更快:

if foo not in A.keys(): 
   A[foo]=x 

或者只是更新

A[foo]=x 

因为当计算机找到foo条目时,它还可以更新它。如果不是,我就要调用哈希表两次?

谢谢。


Tags: inif字典定义foo计算机not情况
3条回答
if foo not in A.keys(): 
    A[foo] = x 

是非常慢的,因为A.keys()创建一个列表,该列表必须在O(N)中解析。

if foo not in A: 
    A[foo] = x 

更快,因为需要O(1)来检查foo中是否存在A

A[foo] = x 

更好,因为您已经有了对象x,您只需添加(如果它已经不存在的话)一个指向该对象的指针到A

只需在字典中添加条目而不检查它们是否存在。我使用3种不同的方法向字典中添加了100000个条目,并使用timeit模块对其进行计时。

  1. if k not in d: d[k] = v
  2. d.setdefault(k, v)
  3. d[k] = v

选项3是最快的,但不是很多。

实际上,我也尝试过if k not in d.keys(): d[k] = v,但速度慢了300倍(每次迭代都会建立一个键列表并执行线性搜索)。它让我的测试太慢了,所以我把它忘在这里了。]

这是我的代码:

import timeit

setup = """
import random
random.seed(0)
item_count = 100000
# divide key range by 5 to ensure lots of duplicates 
items = [(random.randint(0, item_count/5), 0) for i in xrange(item_count)]
"""
in_dict = """
d = {}
for k, v in items:
    if k not in d:
        d[k] = v
"""
set_default = """
d = {}
for k, v in items:
    d.setdefault(k, v)
"""
straight_add = """
d = {}
for k, v in items:
    d[k] = v
"""
print 'in_dict      ', timeit.Timer(in_dict, setup).timeit(1000)
print 'set_default  ', timeit.Timer(set_default, setup).timeit(1000)
print 'straight_add ', timeit.Timer(straight_add, setup).timeit(1000)

结果是:

in_dict       13.090878085
set_default   21.1309413091
straight_add  11.4781760635

注意:这完全没有意义。我们每天都会收到很多关于在Python中使用x或y的最快方法的问题。在大多数情况下,很明显,在遇到任何性能问题之前就已经提出了这个问题。我的建议?专注于写你能写的最清晰的程序,如果它太慢,分析它并在需要的地方进行优化。以我的经验,我几乎从来没有去分析和优化步骤。从问题的描述来看,字典存储似乎不会成为程序中的主要瓶颈。

使用内置的update()函数更快。我在上面对Steven Rumbalski的示例做了一些调整,它显示了update()是如何最快的。至少有两种方法可以使用它(一个元组列表或另一个字典)。前者(如下所示为更新方法1)是最快的。注意,我还改变了一些关于史蒂文·伦巴尔斯基例子的其他事情。我的字典每本都有100000个键,但是新值有10%的几率不需要更新。这种冗余的可能性将取决于您正在更新字典的数据的性质。在我的机器上,我的更新方法1是最快的。

import timeit

setup = """
import random
random.seed(0)
item_count = 100000
existing_dict = dict([(str(i), random.randint(1, 10)) for i in xrange(item_count)])
items = [(str(i), random.randint(1, 10)) for i in xrange(item_count)]
items_dict = dict(items)
"""
in_dict = """
for k, v in items:
    if k not in existing_dict:
        existing_dict[k] = v
"""
set_default = """
for k, v in items:
    existing_dict.setdefault(k, v)
"""
straight_add = """
for k, v in items:
    existing_dict[k] = v
"""
update_method1 = """
existing_dict.update(items)
"""
update_method2 = """
existing_dict.update(items_dict)
"""
print 'in_dict        ', timeit.Timer(in_dict, setup).timeit(1000)
print 'set_default    ', timeit.Timer(set_default, setup).timeit(1000)
print 'straight_add   ', timeit.Timer(straight_add, setup).timeit(1000)
print 'update_method1 ', timeit.Timer(update_method1, setup).timeit(1000)
print 'update_method2 ', timeit.Timer(update_method2, setup).timeit(1000)

此代码产生以下结果:

in_dict         10.6597309113
set_default     19.3389420509
straight_add    11.5891621113
update_method1  7.52693581581
update_method2  9.10132408142

相关问题 更多 >