摘自书中引言
python 中第二个主要的数据结构是字典。你可能记得,字典和列表不同,你可以通过键而不是位置来访问字典中的项目。在本书的后面,你会看到有很多方法来实现字典。字典的 get和 set 操作都是 O(1)。另一个重要的操作是 contains,检查一个键是否在字典中也是 O(1)。所有字典操作的效率总结在 Table 中。关于字典性能的一个重要方面是,我们在表中提供的效率是针对平均性能。 在一些罕见的情况下,contains,get item 和 set item 操作可以退化为O(n)。
list和Dict的contains性能对比
尽管容器的大小在一直增加,字典的耗时依旧很小,而数组耗时线性增加
code
list_nlogn = []
dict_nlogn = []
list_c = Timer("test_list.__contains__(i-1)", "from __main__ import test_list,i")
dict_c = Timer("test_dict.__contains__(i-1)", "from __main__ import test_dict,i")
x = list(range(100,4000,100))
for i in x:
test_list = list(range(i))
list_nlogn.append(list_c.timeit(number = 100))
test_dict = {j:None for j in range(i)}
dict_nlogn.append(dict_c.timeit(number = 100))
plt.plot(x, list_nlogn,marker='o',label='list_nlogn')
plt.plot(x, dict_nlogn,marker='o',label='dict_nlogn')
plt.legend() # 让图例生效
plt.xlabel('n size') # X轴标签
plt.ylabel("time use") # Y轴标签
plt.show()
由于 Python 是一种不断发展的语言,底层总是有变化的。 有关 Python 数据结构性能的最新信息可以在 Python 网站上找到。
https://wiki.python.org/moin/TimeComplexity
__contains__
虽然list和dict都包含__contains__方法,但是两种方法的时间消耗有着巨大差异,list的contains方法获取的是list内的元素,而dict获取的是键,而不是键对应的值,可能python在构建字典时会对键的查找进行优化,就像list的索引对于一个值,而字典的一个键对应一个值。对上述代码做出改动:
list_c = Timer("test_list[i-1]", "from __main__ import test_list,i")
dict_c = Timer("test_dict[i-1]", "from __main__ import test_dict,i")
可以看到性能基本是同步的,而且是平稳线性的,说明列表的索引和字典的键有异曲同工之处。