【发布时间】:2020-04-02 11:49:25
【问题描述】:
我有一个数据结构,它由固定数量的字段和一个递归函数组成,该函数对这些结构的列表进行一些处理。在每次迭代中,该函数都会访问某个特定的列表元素(数据结构),分析其所有字段并(基于字段值)通过删除或添加新的数据结构元素来修改列表。
我想知道实现这种数据结构的最有效方法是什么?我想最敏感的方面是创建新结构和访问结构字段。我对具有 10 个字段的结构进行了一些测试:
- 作为列表实现:
print("List")
def list_f ():
l = [1,2,3,4,5,6,7,8,9,10]
a1 = l[0]
a2 = l[1]
a3 = l[2]
a4 = l[3]
a5 = l[4]
a6 = l[5]
a7 = l[6]
a8 = l[7]
a9 = l[8]
a10 = l[9]
print(timeit("list_f()", "from __main__ import list_f"))
输出:
List
0.4056466743350029
- 作为字典实现:
print("Dict")
def dict_f ():
d = {"1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9, "10":10}
a1 = d["1"]
a2 = d["2"]
a3 = d["3"]
a4 = d["4"]
a5 = d["5"]
a6 = d["6"]
a7 = d["7"]
a8 = d["8"]
a9 = d["9"]
a10 = d["10"]
print(timeit("dict_f()", "from __main__ import dict_f"))
输出:
Dict
0.6061008963733912
- 作为类实现:
print("Class")
class C (object):
def __init__(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10):
self.a1 = a1
self.a2 = a2
self.a3 = a3
self.a4 = a4
self.a5 = a5
self.a6 = a6
self.a7 = a7
self.a8 = a8
self.a9 = a9
self.a10 = a10
def class_f ():
c = C(1,2,3,4,5,6,7,8,9,10)
a1 = c.a1
a2 = c.a2
a3 = c.a3
a4 = c.a4
a5 = c.a5
a6 = c.a6
a7 = c.a7
a8 = c.a8
a9 = c.a9
a10 = c.a10
print(timeit("class_f()", "from __main__ import class_f, C"))
输出:
Class
1.2926895800046623
在我看来,列表是最有效的解决方案。您是否知道我可以尝试的任何其他实现,或者这些执行时间如何取决于结构字段的数量和类型?
编辑:
澄清一下,字段不具有相同的类型(我只是在示例中使用了所有int-s),会有一些字符串,一些对象句柄等等...... 我永远不必即时修改字段。我知道在创建结构时希望它们具有什么值,因此我将初始化它们并将结构插入到列表中。该函数仅读取这些值并在完成时从列表中删除整个结构(并且可以选择创建全新的结构并将其插入输入列表中)。我是定义结构和函数的人,因此我可以调整函数以有效地与任何实现一起工作。
【问题讨论】:
-
恭喜!您刚刚发现设置 dict 比设置列表更昂贵,自定义 Python 类比设置 dict 更昂贵。但我不确定这与关于在递归函数中修改结构的问题有什么关系......
-
为了让你的“基准”有意义,你应该在被测函数之外构建列表/字典/类实例,并且只有函数中的访问部分。
-
你忘了测试
tupleFWIW - 从语义上讲,它是你使用列表的正确类型。 -
感谢@brunodesthuilliers,但我认为创建结构所需的时间也需要考虑在内,因为该函数还可以将新结构添加到列表中。元组给了我:元组 0.32156257471069694
-
“还需要考虑创建结构所花费的时间,因为该函数还可以将新结构添加到列表中” => 嗯,确实如此 - 但您仍然应该分别测试两者得到有用的结果。
标签: python performance data-structures