是否扩展了一个字典列表,而不是迭代密钥?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否扩展了一个字典列表,而不是迭代密钥?相关的知识,希望对你有一定的参考价值。
在帮助我的同事解决问题时,我看到了一些我不知道python的事情。与其他方式相比,我很好奇性能和时间复杂性的堆积,最好的方法是为了性能。
我的同事做了什么促使这个问题:
list_of_keys = []
test_dict = {'foo': 1, 'bar': [1, 2, 3, 4, 5]}
list_of_keys.extend(test_dict)
print(list_of keys)
['foo','bar']
与我见过的其他例子:
list_of_keys = []
test_dict = {'foo': 1, 'bar': [1, 2, 3, 4, 5]}
for i in test_dict.keys():
list_of_keys.append(i)
和
keys = list(test_dict)
为了简单地附加键,这些中的哪一个被证明是最有益的和最pythonic的。哪一个产生最佳性能?
正如the docs解释的那样,s.extend(t)
:
使用
s
的内容扩展t
(大部分与s[len(s):len(s)] = t
相同)
好的,所以不清楚它是否应该比循环中调用append
更快或更慢。但它更快一点 - 循环发生在C而不是Python中,它可以使用一些特殊的优化代码添加到列表中,因为它知道你没有同时触摸列表。
更重要的是,它更简单,更易读,更难出错。
至于从空列表开始然后扩展它(或附加到它),没有充分的理由这样做。如果您已经有一个包含某些值的列表,并且想要添加dict键,那么请使用extend
。但是如果你只是想创建一个密钥列表,那就做list(d)
。
至于d.keys()
与d
,真的没什么区别。无论你迭代dict
还是它的dict_keys
视图,你都会得到完全相同的迭代值,即使使用完全相同的dict_keyiterator
。对keys()
的额外调用确实让事情变得有点慢,但这是一个固定的成本,而不是每个元素一次,所以除非你的指标很小,否则你不会看到任何明显的差异。
那么,在这种情况下,哪一个看起来更具可读性。一般来说,你想要在d.keys()
上循环的唯一原因就是当你想要明确表示你正在迭代dict的键时,但是从周围的代码来看,d
是dict
并不明显。
除此之外,您还询问了复杂性。
所有这些解决方案都具有相同的(线性)复杂性,因为它们在封面下都做同样的事情:对于字典中的每个键,将其附加到列表的末尾。这是每个键的一步,并且每个步骤的复杂性是摊销常数(因为Python列表以指数方式扩展),因此标题时间是O(N)
,其中N
是dict的长度。
在@thebjorn提到模块之后。似乎调用extend是最快的
为了便于阅读和清洁,list()似乎是最pythonic。
最有益的似乎取决于用例。但是,或多或少这样做是多余的,如评论中所述。这是从一个错误中发现的,我很好奇。
timeit.timeit("for i in {'foo': 1, 'bar': [1, 2, 3, 4, 5]}.keys():[].append(i)", number=1000000)
0.6147394659928977
timeit.timeit("[].extend({'foo': 1, 'bar': [1, 2, 3, 4, 5]})", number=1000000)
0.36140396299015265
timeit.timeit("list({'foo': 1, 'bar': [1, 2, 3, 4, 5]})", number=1000000)
0.4726199270080542
以上是关于是否扩展了一个字典列表,而不是迭代密钥?的主要内容,如果未能解决你的问题,请参考以下文章