【问题标题】:Python dictionnary items() method cost inside iterable可迭代中的Python字典项目()方法成本
【发布时间】:2015-04-30 09:18:12
【问题描述】:

我现在还没有进行基准测试,我想知道迭代中字典的 items()(或 keys() 或 values())方法的成本。让我解释一下:

我有 2 个字典(当然,我真正的字典要长得多):

One = {'a': 'dontmind', 'b': 'dontmind', 'c': 'whatever'}
Two = {'a': 'dontmind', 'c': 'dontmind'}

我想检查“Two”的所有键是否都在“One”中,并且会这样做:

if all([key in One.keys() for key in Two.keys()]) :
    # do stuff!

考虑到性能,我想知道这种方式是否更好:

one_keys = One.keys()
two_keys = Two.keys()
if all([key in one_keys for key in two_keys]) :
    # do stuff!

在这种情况下,keys() 方法只为每个 dict 调用一次。我真的不知道从字典中提取键的基本过程,以及这两种方式之间的差异是否真的有意义。你能帮帮我吗?

另外,我应该这样考虑吗?

one_keys = One.keys()
two_keys = Two.keys()
for key in two_keys :
  if key not in one_keys :
    break
else :
  # do stuff!

感谢您的回答。

【问题讨论】:

  • 你用的是什么版本的 Python?
  • 我使用的是 python 2.7

标签: python performance python-2.7 dictionary iterable


【解决方案1】:

如果 Python 2.x,.keys() 返回一个列表,所以多次调用它有点开销......在 3.x 中,它返回一个 dict_keys 对象,该对象具有类似 set 的行为,所以对于 3.x 来说最简单的是:

contains_all = two.keys() <= one.keys()

Python 2.7 中的等价物是viewkeys:

contains_all = two.viewkeys() <= one.viewkeys()

对于早期版本,将two 转换为一个集合并检查它是one 的子集,例如:

contains_all = set(two).issubset(one)

Python 3.x 时序

%timeit two.keys() <= one.keys()
# 1000000 loops, best of 3: 557 ns per loop
%timeit set(two).issubset(one)
# 1000000 loops, best of 3: 732 ns per loop
%timeit all(key in one for key in two)
# 1000000 loops, best of 3: 1.24 µs per loop

Python 2.7 计时(显示.viewkeys()

%timeit two.viewkeys() <= one.viewkeys()
# 1000000 loops, best of 3: 484 ns per loop
%timeit set(two).issubset(one)
# 1000000 loops, best of 3: 677 ns per loop
%timeit all(key in one for key in two)
# 1000000 loops, best of 3: 1.37 µs per loop

【讨论】:

  • &lt;= 在这种情况下对 set 类似的对象 (dict_keys) 进行操作,它等效于 set.issubset - 它检查左侧存在的所有键是否存在于右侧
【解决方案2】:

为了在 2.7(但不是早期版本)和 3.x 中获得最佳性能,我建议这样写:

if all(key in One for key in Two):
    # do stuff!

这避免了几个陷阱:

  • 生成器表达式不会像列表推导那样将整个序列拉入内存。
  • 在 2.x 中,.keys() 返回一个列表。测试列表的成员资格很慢,但测试字典的成员资格很快。在 3.x 中,.keys() 返回一个类似集合的对象,所以这不是问题。
  • 此外,该列表占用了额外的空间,我们在 2.7 下节省了空间。 3.x 的 set-like .keys() 是现有字典的“视图”,所以这在 3.x 下也不是问题。

【讨论】:

  • 感谢您的快速答复!我会试试这个。我打算做一些基准测试,如果你愿意,我会告诉你。
  • @jean.stache:请记住,当我们谈论速度时,我们通常关注的是可扩展性,而不是绝对时间。字典比具有相应索引的两个列表“更快”,因为字典可以合理地扩展到数百或数千个条目,而列表会随着它们变大而变得太慢。如果您正在测试小示例,您可能看不出太大差异,甚至会得到相反的结果。
  • 感谢凯文的建议
猜你喜欢
  • 2012-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多