Python字典items()方法可迭代内部成本

时间:2015-02-27 15:40:59

标签: python performance python-2.7 dictionary iterable

我现在还没有进行基准测试,我想知道迭代中一个字典的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!

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

另外,我应该考虑这种方式吗?

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

感谢您的回答。

2 个答案:

答案 0 :(得分:2)

如果是Python 2.x,.keys()返回一个列表,那么多次调用会有点开销...在3.x中,它返回一个dict_keys对象,其中有{{ 1}} - 类似行为,因此3.x最简单的是:

set

Python 2.7中的等价物是contains_all = two.keys() <= one.keys()

viewkeys

对于早期版本,请将contains_all = two.viewkeys() <= one.viewkeys() 转换为集合并检查它是two的子集,例如:

one

Python 3.x时间

contains_all = set(two).issubset(one)

Python 2.7时序(显示%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

.viewkeys()

答案 1 :(得分:1)

为了获得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的类似集.keys()是现有字典的“视图”,所以这在3.x下也不是问题。