【发布时间】:2012-06-22 23:13:09
【问题描述】:
我需要展平一些嵌套列表。写完 flatten 函数后,我自然是想看看有多少种方法可以破解它。我终于通过 pypy 运行它,很高兴地发现当列表变得非常深时,pypy 的运行速度明显快于 cpython。
但是,我看到了一个奇怪的情况,一个更大、更复杂的列表、更多种类的元素的测试实际上比“更简单”的列表执行得更快。
元素较少的测试 1 的运行速度始终比测试 2 慢大约一秒(使用时间 pypy ./script.py)。
def flatten(lol):
if not any([isinstance(i, list) for i in lol]):
return lol
flatter = [i for i in lol if not isinstance(i, list)]
for sublist in lol:
if isinstance(sublist, list):
flatter.extend(sublist)
return flatten(flatter)
def silly(l):
return [l, [l]]
nested_function = [["kaplutis", ["mucus", ["my brain", ["is","filled",["with",["pus",]]]]]], "santa gertrudis",[[[[["innermost",flatten(["in", "func"])]]]]]]
tuples = ["empty tuple retained-->", (), ("2-tuple not flattened",), ("I'm the only thing in this tuple")]
dicts = [{"hip": "hop", "ster": "toad"}]
lone_dict = {"lone": 1, "dict": 2}
silly_list = ["1"]
for i in range(20):
silly_list = silly(silly_list)
# test 1 - only the absurdly nested list
print(len(flatten(silly_list)))
# test 2 - absurdly nested list, with
lol = [nested_function, tuples, dicts, lone_dict, silly_list]
print(len(flatten(lol)))
我唯一能想到的是,当 JIT 在第二个测试中处理“silly_list”之前的更简单的嵌套列表时,我遇到了一些意外优化。
【问题讨论】:
-
澄清:使用 python 2.7.2、python 3.2.2 和 pypy 1.9(来自 pypy-1.9-linux64.tar.bz2 的二进制文件)运行测试,全部在 ubuntu 12.04 x86_64 上运行。
-
另外:请忽略我的测试用例中的愚蠢值,我倾向于将脑海中出现的任何东西都粘在上面,并且不认为它们可能会分散注意力。 (没有人抱怨过这一点,但一天后看它,我发现它可能会导致人们不那么认真地对待这个问题)。谢谢。
-
进一步澄清:测试应该单独运行,首先通过cominting out "lol = [nested_function, tuples, dicts, lone_dict, silly_list]" 和 "print(len(flatten(lol)))" ,然后使用 /usr/bin/time 运行,然后在注释掉“print(len(flatten(silly_list)))”后重复测试。这应该首先解释。谢谢。
-
不要评论你自己的问题,update它。
-
将不必要的
[]放入any()。运行探查器。循环运行每个测试以排除 jit 预热时间。见Analysing python's performance under PyPy