Python iterable 中的字典 items() 方法成本
Python dictionnary items() method cost inside 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!
在这种情况下,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.7(但不是更早的版本)和 3.x 中获得最佳性能,我建议这样写:
if all(key in One for key in Two):
# do stuff!
这避免了几个陷阱:
- 生成器表达式不会像列表理解那样将整个序列拉入内存。
- 在2.x、
.keys()
、returns列表中。测试列表的成员资格很慢,但测试字典的成员资格很快。在3.x、.keys()
、returns一个set-like对象中,所以这不是问题。
- 此外,该列表占用额外 space,我们将其保存在 2.7 下。 3.x 的类集合
.keys()
是现有字典的 "view",所以这在 3.x. 下也不是问题
如果Python 2.x, .keys()
returns 一个列表,那么多次调用它有点开销......在3.x ,它 returns 一个具有 set
行为的 dict_keys
对象,因此 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
我现在还没有进行基准测试,我想知道可迭代对象中字典的 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() 方法只为每个字典调用一次。我真的不知道从字典中提取键的基本过程,以及这两种方式之间的区别是否真的很重要。你能帮帮我吗?
另外,我应该这样考虑吗?
one_keys = One.keys()
two_keys = Two.keys()
for key in two_keys :
if key not in one_keys :
break
else :
# do stuff!
感谢您的回答。
为了在 2.7(但不是更早的版本)和 3.x 中获得最佳性能,我建议这样写:
if all(key in One for key in Two):
# do stuff!
这避免了几个陷阱:
- 生成器表达式不会像列表理解那样将整个序列拉入内存。
- 在2.x、
.keys()
、returns列表中。测试列表的成员资格很慢,但测试字典的成员资格很快。在3.x、.keys()
、returns一个set-like对象中,所以这不是问题。 - 此外,该列表占用额外 space,我们将其保存在 2.7 下。 3.x 的类集合
.keys()
是现有字典的 "view",所以这在 3.x. 下也不是问题
如果Python 2.x, .keys()
returns 一个列表,那么多次调用它有点开销......在3.x ,它 returns 一个具有 set
行为的 dict_keys
对象,因此 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