PEP 3106 建议更慢的方式?为啥?
Posted
技术标签:
【中文标题】PEP 3106 建议更慢的方式?为啥?【英文标题】:PEP 3106 suggests slower way? Why?PEP 3106 建议更慢的方式?为什么? 【发布时间】:2018-08-29 06:26:36 【问题描述】:最近,我不得不将字典的值转换为 Python 3.6 中的列表和一个应该经常发生这种情况的用例。 为了成为一个好人,我想使用一个接近 PEP 的解决方案。现在,PEP 3106 建议
list(d.keys())
这显然工作正常 - 但是在我看到的 Windows 7 机器上使用 timeit
>python -m timeit "[*'a': 1, 'b': 2.values()]"
1000000 loops, best of 3: 0.249 usec per loop
>python -m timeit "list('a': 1, 'b': 2.values())"
1000000 loops, best of 3: 0.362 usec per loop
我认为后一个版本有优势,因为否则 PEP 为何会建议速度较慢的版本。
所以我的问题来了:后一个版本与第一个版本相比有什么优势?
【问题讨论】:
PEP 3106 是在 Python 中存在第一个语法之前编写的。如果可以依赖那里的性能差异,我会感到惊讶 - 我看不出第一个应该具有更好性能的原因。 这个性能对你来说重要吗?如果是这样,为什么?在很多很多情况下,您都可以在 PEP 中找到可优化的代码变体。微优化不是 PEP 的目的。 @GarethLatty 这增加了超过 45% 的运行时间。我的印象太巧合了。 @jpp 老实说,我认为这个“微优化”(非常好的术语,我喜欢它)根本不重要。我只是好奇,因为我不是“真正的”程序员,想看看解决方案之间的比较。 @month 我在答案中添加了一个性能部分,您使用的测试过于简单,无法声称增加 45%。我的猜测是查找list
名称(可能会反弹)的成本,而不是列表文字的成本。
【参考方案1】:
答案是因为更快的语法是在 2013 年在 PEP 448 中首次引入的,而您引用的 PEP 3106 是在 2006 年编写的,所以即使现在确实更快,但它在 PEP 时并不存在写好了。
正如其他人所指出的,PEP 的作用不是为尽可能快的代码提供模板 - 通常,PEP 中的代码旨在尽可能简单和清晰,因为示例通常是关于理解概念而不是达到最好的结果,所以即使当时确实存在语法,并且以真实(和可靠)的方式更快,它仍然可能没有被使用。
用更大的值进一步测试:
python -m timeit -s "x = [1]*10000" "[*x]"
10000 loops, best of 3: 44.6 usec per loop
python -m timeit -s "x = [1]*10000" "list(x)"
10000 loops, best of 3: 44.8 usec per loop
显示差异并不是真正的两倍,而是固定成本 - 我猜这是查找 list()
内置函数的成本。在大多数实际情况下,这可以忽略不计。
【讨论】:
不知道 PEP 号码不是按他们的介绍排序的。谢谢!以上是关于PEP 3106 建议更慢的方式?为啥?的主要内容,如果未能解决你的问题,请参考以下文章